函数
1. void返回值,可以不写return,也可以在需要返回的地方写return;
2. 返回值有三种,变量、指针、引用,与实参赋值形参是一样的,变量和指针都是基于拷贝的,引用不是拷贝。指针指向的内容没有拷贝。
main(){
int a=10;
}
int f1(int i) { // 返回变量,直接返回即可,复制i后返回。
return i;
}
int *f2(int i) { // 返回指针,等价于int *temp=&i;return *temp; 复制一个指向i的指针后返回。
return &i;
}
int &f3(int i) { // 返回引用,和实参传入形参的方式相同,返回i即可,返回值即是实参i本身,没有复制。
return i;
}
const int& f4(int i) {
return i; // 正确,f4(a)相当于const int temp=a;
}
3. 返回引用和指针时,不能指向函数内的对象,因为它们会销毁,只能引用或指向形参中的变量。返回变量可以随意,因为返回的是拷贝的副本。
4. 返回vector
vector<string> f() {
return {"abc","def"}; // 用{}返回vector,类似于vector初始化
}
5. 返回数组
int (*function(int i))[10]; // 数组不可以被拷贝,所以只能返回指针或引用
int arr[] = {1,2,3};
main() {
for (auto i:*function()) { // function()是&arr头指针的地址 *function()是arr头指针,也是数组名
cout<<i<<endl; // 1 2 3
}
cout<<**function()<<endl; // 1 **function()等于*arr
}
int (*function())[3] { // [3]不可省略
return &arr; // 不能返回arr,因为arr指向的是头元素,不是arr[3],必须返回指向arr的指针,也就是头元素的指针的指针
}
6. 函数名相同,形参列表不同是重载,形参列表相同,返回值不同不是重载,main函数不能重载。
void f(int a); // 普通变量加const不算重载
void f(const int a);
void f(int *p); // 指针的顶层const不算重载
void f(int * const p);
void f(int *p); // 指针的底层const是重载
void f(const int *p);
void f(int &r); // 引用加const是重载
void f(const int &r);
7. const_cast在重载中的使用
const string& f(const string &s) {
return s;
}
string& f(string &s) {
auto temp = f(const_cast<const string&>(s)); // 利用const_cast先加上const
return const_cast<string&>(temp); // 再利用const_cast去掉const
}
8. 作用域同名变量、函数名都可以隐藏外部,C语言中,先查找名字,再检查类型。
int read(int i);
int print(int a);
void f() {
int a = 10;
int read = 0;
read(a); // 错误,read被隐藏了
void print();
print(a); // 错误,print被隐藏了,不要在函数中声明函数
}
9. 默认实参
定义时,默认实参后面必须都是默认的。函数内局部变量不能被声明成实参的值。
声明时,如果要分多次声明:
void f(a,b,c=10); // OK
void f(a,b,c=20); // 错误,已经声明了c
void f(a=10,b=10,c); //OK
10. 内联函数,在编译时,在函数名处展开函数,避免了运行时函数的开销。一般定义在头文件中。前面加上inline
inline int f(int i) {
return i+1;
}
main() {
int a=10;
cout<<f(a)<<endl; // 等价于cout<<i+1<<endl;
}
11. assert NDEBUG
#define NDEBUG // NDEBUG表示非调试模式,所有assert不起作用。默认为#define DEBUG开启调试模式
main () {
int a=10;
assert(a == 20); // 在DEBUG模式下,assert为真才继续执行
}
还有几个宏用于调试:__func__当前函数名 __FILE__当前文件名 __LINE__当前行数 __TIME__编译时间 __DATE__编译日期12. 重载如何匹配最优函数
当两个重载函数的优先级相同时,出现二义性错误,返回错误。
优先级从高至低:完全匹配->只差一个const->隐式类型转换(char提升至int)->损失精度隐式类型转换(double变成int )
void f(int);
void f(short);
char a='A‘; // char提升到int,使用int
void f(float);
void f(long);
double d=1.2; // 损失精度的类型转换无法比较哪个更优,二义性错误