第 6 章:函数
6.1 函数基础
一个函数(Function)包括:返回类型(return type)、函数名、由 0 个或多个形参(parameter)形成的列表以及函数体。
通过调用运算符(call operator)来执行函数。
形参和实参
实惨是形参的初始值。
函数的形参列表
空的形参列表可以如下,隐式定义或显式定义
void f1() {}
void f2(void) {}
函数的返回类型
一种特殊的返回类型是 void
,表示不返回任何值。
6.1.1 局部对象
名字有作用域、对象有生命周期(lifetime)
形参和函数体内部定义的变量统称为局部变量(local variable)
自动对象
函数开始时申请存储空间,函数结束后自动对象的值变成未定义。
形参是一种自动对象。
局部静态对象
令局部变量的生命周期贯穿函数调用以及之后的时间。
static int i = 0;
6.1.2 函数声明
函数的三要素(返回类型、函数名、形参类型)描述了函数的接口,说明了调用该函数所需的全部信息。函数声明也称作函数原型(function prototype)。
void print (int a, int b);
含有函数声明的头文件应该被包含到定义函数的源文件中。
6.2 参数传递
形参初始化的机理与变量初始化一样。
形参是引用类型:实参被引用传递(passed by reference),函数被引用调用(called by reference)。
当实参的值被拷贝给形参时,形参和实参是两个相互独立的对象:实参被值传递(passed by value),函数被传值调用(called by value)。
传值参数
✨在 C++ 语言中,建议使用引用类型的形参替代指针。
void fn (int *ip);
fn(&iv);
传引用参数
void fn (int &ir);
fn(iv);
使用引用避免拷贝。
✨如果函数无须改变引用形参的值,最好将其声明为常量引用。
使用引用形参“返回”额外信息
实际是通过改变引用形参,来达到目的。
const 形参和实参
尽量使用常量引用
数组形参
main:处理命令行选项
int main (int argc, char *argv[]) {}
int main (int argc, char **argv) {}
当执行 prog -d -o file
。
argv[0] ---- prog
argv[1] ---- -d
argv[2] ---- -0
argv[3] ---- file
如上,从 argv[1] 开始拿参数,argv[0] 为程序名。
含有可变形参的函数
有时候无法提前预知应该向函数传递几个实参。
initializer_list
也是一种模版类型,它的元素永远都是常量。
error_msg({ "functionX", "some error" })
省略符形参
这种方式是为了 c++ 程序访问某些特殊 c 代码。
省略符形参应该仅仅用于 C 和 C++ 通用的类型
省略符形参所对应的实参无须类型检查
void foo(parm_list, ...);
void foo(...);
6.3 返回类型和 return 语句
return;
return expression;
无返回值函数
在返回类型是 void 的函数中使用无返回值函数。会在最后隐式的 return。
有返回值函数
只要返回类型不是 void 的函数,都必须 return 对应类型的值。
不要返回局部对象的引用或指针。
函数结束时临时对象的占用空间会被释放掉,return 语句将会指向不再可用的内存空间。
主函数 mian 的返回值
mian 函数的返回值可以看作是状态指示器。返回 0 表示成功,返回其他表示失败。
返回数组指针
因为数组不能被拷贝,所以函数不能返回数组。可以返回数组的指针或引用。
Type (*function (parameter_list))[dimension];
Type 表示元素的类型,dimension 表示数组的大小。
int (*func(int i))[10];
使用尾置返回类型
auto func(int i) -> int(*)[10]
6.4 函数重载
mian 函数不能重载。
最好只重载那些非常相似的操作。
调用匹配的重载函数的过程叫函数匹配(重载确定)。
匹配结果:最佳匹配、无匹配、匹配到太多的(二义性调用)。
重载与作用域
如果在内层作用域中声明名字,将会隐藏外层作用域中的同名实体。
6.5 特殊用途语言特性
默认实参
string screen(int a = 10, char b = '');
通常,应该在函数声明中指定默认实参,并将该声明放在合适的头文件中。
内联函数和 constexpr 函数
内联函数可以避免函数开销的调用
在编译过程中 shorterString("xx", "xx")
会被展开成他的函数内容。
一般来说,内联机制用于优化规模较小、流程直接、频繁调用的函数。
inline const string shorterString(const string &str1, const string &str2);
constexpr 函数
函数的返回类型以及所有形参都必须是字面值类型。函数体只有一条 return 语句。
constexpr 函数不一定返回常量表达式。
constexpr int new_sz() { return 42; }
调试帮助
assert(expr);
_ FILE _ 存放文件名的字符串字面值。
_ LINE _ 存放当前行号的整型字面值。
_ TIME _ 存放文件编译时间的字符串字面值。
_ DATE _ 存放文件编译日期的字符串字面值。
6.6 函数匹配
候选函数:
与被调用的函数同名
声明在调用点可见
可行函数:
形参数量和提供实参数量相等
类型一一相等,或能转换
实参类型转换
- 精确匹配
- 通过 const 转换实现
- 通过类型提升实现
- 通过算数类型转换
- 通过类型转换
6.7 函数指针
函数指针指向函数,而非对象。
pf 是一个指针指向一个函数。
bool (*pf) (const int &);
pf 是一个函数,返回 bool *
类型。
bool *pf (const int &);