第 7 章 函数—— C++ 的编程模块
7.1 复习函数的基本知识
C++ 函数不能直接返回数组,但是可以把数组当成对象的组成部分返回。
函数将返回值复制到指定的 CPU 寄存器或内存中,随后调用程序查看该内存单元。
仅当转化有意义时,原型自动将被传递的参数转换成期望的类型。
7.2 函数参数和按值传递
调用函数时,函数将创建新的变量并将其初始化为传入参数的值,因此函数执行的操作将不会影响传入参数的值。
交替乘除相比于累乘累除可以避免中间结果超过最大浮点数。
7.3 函数和数组
当用于函数头或函数原型时,int *arr
和 int arr[]
的含义是相同的。
当使用数组作为函数参数时,必须显式地声明数组长度,因为对于形参来说 sizeof arr
只是形参指针本身的长度,指针本身并没有存储数组的大小。
声明形参时可以使用 const
关键字以保证数组内容不会被修改。
对于处理数组的函数,除了传递数组起始处指针和数组长度以外,还可以传递数组开头和尾部两个指针。
int age = 28; const int *p = &age;
中,不允许通过 *p = 18;
修改数值,但可以通过 age = 18;
修改,因为 *p
被声明为 const
变量,而 age
不是 const
变量。
指针指向常量对象时,可以防止使用指针修改值;将指针本身声明为常量时,可以防止改变指针指向的方向。
禁止将 const
变量地址赋给非 const
指针。
int age = 28; const int *p = &age;
中,允许通过 int sage = 80; p = &sage;
修改 p
的值,因为 p
本身并不是 const
对象,声明为 int * const p = &age;
可以防止 p
指向被修改,但可以使用 *p = 18;*
修改数值。
7.4 函数和二维数组
对于二维数组作为函数参数的情况,int sum(int *(arr)[4], int size);
和 int sum(int arr[][4], int size);
的原型含义完全相同,这两个原型都指出 arr
是指向数组的指针。
arr[r][c] == *(*(arr + r) + c);
。
7.5 函数和 C 风格字符串
字符串函数原型应该将形参声明为 char *
类型,字符串内置结束字符 \0
,因此不需要传入字符串长度。
处理字符串的标准方式为 while (*str) { ...; str++; }
。
7.6 函数和结构
在默认情况下,C++ 函数按值传递参数,像普通变量一样复制结构,函数使用原始结构的副本。
将 cin >>
作为测试条件可以有效排除异常输入值。
7.7 函数和 string
对象
string
对象7.8 函数与 array
对象
array
对象7.9 递归
7.10 函数指针
如果 think()
是一个函数,则 think
就是函数的地址。
如果函数原型为 double think(int);
,则函数指针声明为 double (*pf)(int);
,函数指针声明需要包含返回类型和参数列表,需要加上括号防止 *pf(int)
表示为返回指针的函数,使用 pf = think;
赋值。
使用 (*pf)(10);
或 pf(10);
来调用函数。
使用 double *(*pa[3])(int) = {f1, f2, f3};
声明并初始化函数指针数组。这里不能使用 auto
因为自动推断类型只适用于单值初始化而不能用于列表。使用 double *(*(*pd)[3])(int) = &pa;
获得指向数组的指针。
使用 typedef
简化函数指针的声明,使用 typedef double (*p_fun)(int);
创建类型别名。