函数基础
函数体,形参和实参(实参是形参的初始值 );
形参列表;返回类型。
局部对象
- 自动对象。定义的变量属于此类
- 局部静态对象。通过static定义的变量。在程序执行过程中一直有效。,知道程序结束才会被销毁。
分离式编译
参数传递
- 传值参数
通过拷贝变量,或者指针来访问。 - 传引用
尽量使用传引用来避免拷贝。
const与参数
实际就是const的使用,底层const和顶层const
在参数传递的时候会忽略顶层const。就是说可以使用一个变量来初始化一个常量形参。
数组参数
- 下面三个是等价的
void pri(int *p)
void pri(int p[])
void pri(int p[10])
- 传递多维数组
下面两个是等价的
void pri(int (*matrix)[],int size)
void pri(int matrix[][],int size)
含有可变形参的函数
- 如果参数的类型都是一样的,那么可以使用initializer——list类型的形参。
int f(initializer_list<int>shu);
int main()
{
cout << f({ 1, 2, 3 }) << endl;
cout << f({ 3,4 }) << endl;
//注意要使用大括号
return 0;
}
int f(initializer_list<int>shu)
{
int ans = 0;
for (auto i = shu.begin(); i != shu.end(); ++i)
{
ans += (*i) * (*i);
}
return ans;
}
要注意使用大括号。
返回类型
返回引用将返回一个左值,其他返回类型是右值。
函数重载
- 函数重载会忽略顶层const
- 重载函数应该只从重载相似的操作。
- 使用const_cast和重载
- 在C++中名字查找在类型检查之前,所以不要使得函数和变量重名。
特殊的语言特性
默认实参
默认实参必须放在所有未定义默认实参的形参后面
内联函数
内联函数只是一个请求,编译器可以忽略(如果函数太大,或是产生了递归);
constexpr函数
- 只能用于常量表达式的函数
- 函数的所有形参类型(实参)和返回类型都必须是字面值类型。
- 函数体有且仅有一条return语句,且这条return语句一定要能够执行。
调试帮助
assert预处理宏和NDEBUG预处理变量
assert(expr);当expr不成立时,程序会退出并输出信息。
如果定义了NDEBUG那么assert什么也不做。
保留变量
都是两个_
- __func__当前调用函数的名字
- __FILE__存放文件名的字符串字面值
- __LINE__行号
- __TIME__文件编译时间
- __DATE__编译日期
重载函数的函数匹配
- 确定候选函数,所有同名的重载函数
- 确定可行函数。形参数量匹配,类型匹配或者可以转化为形参的类型。(如果具有默认值,那么可行函数形参可能多余实参)
- 寻找最佳匹配。基本思想是:实参类型和形参类型越接近,那么就匹配越好。
- 多个形参匹配遵行下述原则:
该函数的每一个实参匹配都不劣与其他可行函数。
至少有一个实参匹配优于其他可行函数
如果没找到这样的函数,编译器会报出二义性的错误。
实参转换分为以下几个等级
- 精确匹配。
- 实参和形参类型完全一样。
- 数组,函数类型转换为对应的指针
- 添加顶层const或者去除顶层const
- 通过const转化实现的匹配
- 通过类型提升实现的匹配
- 通过算术类型转换或者指针转换实现的匹配
- 通过类类型转换实现的匹配。
函数指针
基本和C++Primer Plus一致。
此外还介绍了
- 可以将函数指针作为函数的形参
- 函数指针还可以作为返回类型(常使用后置返回类型)