1. 函数的形参,实参,返回值,以及如何传参
变量:函数中要分辨形参/实参,实参类型应当与形参匹配,或者能够转换成形参类型。局部变量与全局变量的作用范围。函数内的局部变量作用在函数内,函数调用完,返回后即销毁;函数内可以定义静态变量,作用域可以延伸到函数外。
函数的声明和定义。函数声明可以定义在头文件(.h)文件中,定义则写到源文件中。
2. 函数的参数传递
非引用参数:
普通传值参数。此时实参拷贝给形参。由于是拷贝,形参与原参数是独立的,对参数的改变不会改变原参数。
传指针参数。使用指针参数可以访问原参数的地址,因此可以改变原参数的值。
/*
void func(int *p){
*p=0; //原实参数值修改为0
}
*/
传引用参数:
某些参数在拷贝时比较低效,且占用内存,或者不能拷贝。因此需要通过引用方式传参。引用形参也是对原变量的引用,对形参的修改就是对原变量的修改。
函数通过引用形参提供了一种获取运算结果的方式。
/*
int num=0;
iostream& func(iostream &os, int &num){num++; os<<num<<endl; return os;} //输出num=1;
*/
3. 传数组参数
数组形参与实参的使用。首先,数组有两个特性,即数组不允许拷贝,数组在使用时通常会转换为指向头元素的指针。
因此,传数组参数时,通常是使用指针或者引用传数组参数。指针数组形参书写: int func(int *arr); int func(int arr[]); int func(int arr[10]);写法等价。实参书写: int arr[]= {1, 2, 3}; func(arr);//因为arr自动转换为指针形式,故直接写arr。
问题: 数组没有内置的size成员,使用时如何控制不越界?Ans: 传数组时通常需要传一个size表示数组大小。 //void print(const int *arr, size_t size){};
引用数组形参书写: void print(int (&arr)[]); //&arr两端的括号不能少。引用的实参书写: int arr[10]= {0}; print(arr);
由于数组等效于指针。多维数组其实是存放指针的数组,int (*matrix)[10]; //等效int matrix[][10];编译时会自动忽略第一个维度,而必须要给出第二个维度,即每个一维数组的大小。
4. 函数的返回值类型
无返回值使用void。有返回值类型则定义返回类型,通过return语句返回。实际返回值应当能转换成返回类型。
问题:函数在返回时,进行了什么操作?
答:返回非引用类型时,做了一个拷贝操作。返回引用类型时引用的变量是指向原变量。注意一个问题,函数内部的局部变量在调用结束后会销毁,引用此返回结果会报错。(不要返回局部对象的引用或者指针)
调用运算符的优先级与点运算符和箭头运算符相同,且符合左结合律。因此当函数返回一个指针,引用,类类型时可以通过点,箭头运算符访问结果对象的成员。// func().print().
引用返回一个左值对象,可以放到赋值运算符的左侧,其他返回类型是右值类型。
5. 返回数组指针
首先,返回数组指针的函数形式为: int (*func(int i))[10]。其中(*func(int i))的外层括号不能少,表示数组维度的不能少。
其次,可以使用尾置返回类型声明一个返回数组指针的函数。auto func(int i) -> int (*)[10]。
最后,可以使用decltype声明一个返回数组指针的函数。int arr[]= {}; decltype(arr) *func();