• C++学习笔记(七):函数


    函数通用格式:

    1 typeName functionName(parameterList)
    2 {
    3     //statements
    4     return value;//value is type cast to type typeName
    5 }

    函数原型:

    C++的函数必须提供一个函数原型;

    1 int add(int a, int b);//函数原型
    2 int add(int, int);//也可以省略掉参数名称
    3 
    4 //函数定义
    5 int add(int a, int b)
    6 {
    7     return a + b;
    8 }

    函数参数详解

    形参和实参:

     1 void add(int a, int b)
     2 {
     3     int c = a + b;
     4     cout << c;
     5 }
     6 
     7 void main()
     8 {
     9     int i=1, j=2;
    10     add(i, j);
    11 }

    上面的示例中a和b是形参,i和j是实参。

    参数传递:

    C++中存在3种参数传递的方式;

    (1)值传递

    这时传给形参的是变量的值,传递是单向的。如果在执行函数期间形参的值发生变化,并不传回给实参。因为在调用函数时,形参和实参不是同一个存储单元。

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 int main()
     6 {
     7     void swap(int,int);//函数声明
     8     int i=3,j=5;
     9     swap(i,j);//调用函数swap
    10     cout<<i<<" "<<j<<endl;//i和j的值未互换
    11     return 0;
    12 }
    13 
    14 void swap(int a,int b)//企图通过形参a和b的值互换,实现实参i和j的值互换
    15 {
    16     int temp;
    17     temp=a;//以下3行用来实现a和b的值互换
    18     a=b;
    19     b=temp;
    20 }

    (2)指针传递

    形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。

    这种虚实结合的方法仍然是“值传递”方式,只是实参的值是变量的地址而已。通过形参指针变量访问主函数中的变量(i和j),并改变它们的值。这样就能得到正确结果,但是在概念上却是兜了一个圈子
    ,不那么直截了当。

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 int main()
     6 {
     7     void swap(int *,int *);//函数声明
     8     int i=3,j=5;
     9     swap(&i,&j);//实参是变量的地址
    10     cout<<i<<" "<<j<<endl;//i和j的值已互换
    11     return 0;
    12 }
    13 
    14 void swap(int *p1,int *p2)//形参是指针变量
    15 {
    16     int temp;
    17     temp=*p1;//以下3行用来实现a和b的值互换
    18     *p1=*p2;
    19     *p2=temp;
    20 }

    (3)引用传递

    参数变为实参的一个别名,形参和实参都是同一个对象;就和Java语言的非基元数据类型参数效果一致,使用比指针传递更加方便;

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 int main()
     6 {
     7     void swap(int &,int &);
     8     int i=3,j=5;
     9     swap(i,j);
    10     cout<<"i="<<i<<" "<<"j="<<j<<endl;//i和j的值已互换
    11     return 0;
    12 }
    13 
    14 void swap(int &a,int &b)//形参是引用类型
    15 {
    16     int temp;
    17     temp=a;
    18     a=b;
    19     b=temp;
    20 }

    函数参数使用const修饰:

    表示函数体中不能修改参数的值(包括参数本身的值或者参数其中包含的值)。

    1 void function(const int Var); //传递过来的参数在函数内不可以改变(无意义,因为Var本身就是形参)
    2 
    3 void function(const char* Var); //参数指针所指内容为常量不可变
    4 
    5 void function(char* const Var); //参数指针本身为常量不可变(也无意义, 因为char* Var也是形参)
    6 
    7 void function(const Class& Var);//引用参数在函数内不可以改变
    8 
    9 void function(const TYPE& Var); //引用参数在函数内为常量不可变

    函数返回详解

    主函数main的返回值:

    这里提及一点,返回0表示程序运行成功。

    返回非引用类型:

    函数的返回值用于初始化在跳用函数出创建的临时对象。用函数返回值初始化临时对象与用实参初始化形参的方法是一样 的。如果返回类型不是引用,在调用函数的地方会将函数返回值复制给临时对象。
    且其返回值既可以是局部对象,也可以是求解表达式的结果。

    返回指针类型:

    函数可以返回某种对象的内存地址即指针。

    1 float *func()
    2 {
    3     float *buf = new float[5];
    4     return buf;
    5 }

    返回引用:

    当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身。

    返回引用的注意事项:

    (1)返回引用,要求在函数的参数中,包含有以引用方式或指针方式存在的,需要被返回的参数。比如:

     1 int& abc(int a, int b, int c, int& result)
     2 {
     3     result = a + b + c;
     4     return result;
     5 }
     6 //这种形式也可改写为:
     7 int& abc(int a, int b, int c, int *result)
     8 {
     9     *result = a + b + c;
    10     return *result;
    11 }
    12 //但是,如下的形式是不可以的:
    13 int& abc(int a, int b, int c)
    14 {
    15     return a + b + c;
    16 }

    (2)千万不要返回局部对象的引用。当函数执行完毕时,将释放分配给局部对象的存储空间。此时,对局部对象的引用就会指向不确定的内存。如:

    1 const string &manip(const string &s)
    2 {
    3     string ret = s;
    4     return ret;//wrong:returning reference to a local object
    5 }

    函数和const详解

    1 const int foo(int a);
    2 const int foo(int a) const;

    当const在函数名前面的时候修饰的是函数返回值,失去了左值的作用,但是省去拷贝,增加效率。

    在函数名后面表示是常成员函数,该函数不能修改对象内的任何成员,只能发生读操作,不能发生写操作。

    内联函数

    内联函数使用inline进行标记,表示该函数最终在程序中会被复制到调用的地方,而不是作为函数进行调用,从而获得效率的提升。

    注意:具有循环和switch语句的函数不能作为内联函数。

  • 相关阅读:
    logback 常用配置详解(二) <appender>
    logback 配置详解(一)
    logstash报错如下:Validation Failed: 1: this action would add [2] total shards, but this cluster currently has [999]/[1000] maximum shards open
    从字节码角度分析Byte类型变量b++和++b
    接口和抽象类有什么区别?你选择使用接口和抽象类的依据是什么?
    计算1至n中数字X出现的次数
    转:轻松搞定面试中的红黑树问题
    转:40个Java集合面试问题和答案
    自定义Adapter为什么会重复多轮调用getView?——原来是ListView.onMeasure在作祟
    何时调用getView?——从源码的角度给出解答
  • 原文地址:https://www.cnblogs.com/hammerc/p/4022903.html
Copyright © 2020-2023  润新知