坑!c++
int f(i++,i) //默认是不清楚先计算i仍是i++的,没有规定实参的求值顺序,可是,能够假设从后往前计算,c语言中是这个过程 int f(int a,int) //形参名是可选的,通常状况下须要一个名字,不提供也行,就是找不到这个形参 int f() {
static int a=0;
//这个局部静态对象的生命周期是一直到整个进程结束!进程!
//未显式初始化则默认初始化为0(内置类型)
}
int f(int ,int);
//声明里面不必定须要形参名,注意是声明!
//函数三要素:返回类型(不写其实默认为int),函数名,形参类型
int f(int &a,int &b) //传引用,可修改 //可是不能够传一个字面值,好比f(1,2),引用类型不能够初始化为字面值 int f(const int &a,const int &b) //这就能够了。。。。f(1,2)没有问题 //使用引用能够避免拷贝,特别大的字符串的时候! //传递数组的时候,实际上传递的是数组的指针 //多维数组就不说了 //若是有问题,想一想这样初始化这个形参是否会出现问题 复制代码
若是不清楚形参的数量,可使用省略符形参数组
void foo(int a,...) void foo(...) 复制代码
在含有return语句的循环后面应该也有一条return语句,若是没有的话就是错误的,若是编译器没有发现这个错误,则运行时的行为就是未定义的。函数
for(int i=0;i<n;i++)
if(i>8)
return;
return; //必须写以防止最后不返回
复制代码
不要返回局部对象的引用或者指针,局部变量使用的空间在函数结束后是会被释放的,因此不能够返回局部变量的指针或者引用。可是返回局部变量的值是能够的,由于使用的是拷贝的数据。ui
const string &manip() {
string ret;
if(!ret.empty())
return ret; //错误,返回局部变量的引用
else
return "abv"; //错误,这是一个局部临时量,在函数结束的时候同样会被清空空间
}
复制代码
返回类类型或者引用,指针之类的函数,可使用函数调用的结果访问其成员spa
auto z=shorterString(s1,s2).size();
//返回一个引用类型的函数能够当作左值
char &get_val(string &s,int x) {return s[x];}
int main() {
get_val(s,x)=1; //直接当作左值修改
}
复制代码
也可使用列表初始化返回指针
return {1,2,3} //通常用来返回容器类型
复制代码
若是同一做用域内的几个函数名字相同可是形参列表不一样(形参数量或形参类型),则称之为重载函数。code
注意:main函数是不能重载的对象
int fun(int a,int b);
int fun(int a) int fun(char c) int fun(int c) //这就不是重载 int fun(int) //这也不是重载 复制代码
注意,函数参数是不承认顶层const的,因此默认顶层const加不加都同样。生命周期
int fun(int a);
int fun(const int a); //不能够,顶层const
int fun(int *a);
int fun(int * const a); //不能够,顶层const
//若是形参是某种类型的指针或者引用,则经过区分其指向的是常量对象仍是很是量对象能够实现函数重载,此时const是底层的
int fun(int &);
int fun(const int &); //能够重载,底层const
int fun(int *);
int fun(const int *); //能够重载,底层const
复制代码
注意须要避免函数重载的二义性!进程
在不一样的做用域中没法重载函数!
能够为函数形参赋值默认实参(在声明中赋值)
int fun(int a,int b,int c=1);
//能够为一个或者多个形参赋值默认值,可是,一旦一个形参赋值了,则后面的形参都必须有默认实参
int fun(int a,int b=1,int c); //没法分辨fun(1,2)的二义性
//注意没法修改一个已经存在的默认值
int fun(int ,int ,int c=2); //错误
//可是能够添加默认实参
int fun(int a,int b=2,int c=1); //正确
##函数调用时实参按其位置解析,默认实参负责填补函数调用缺乏的尾部实参
int fun(string a="123",int a=1,int b=2);
fun(,2,3); //错误,默认补充尾部默认参数,想修改哪一个那前面的都不能跳过!
//只能忽略尾部的实参
fun("1",2+1); //假如想修改b这个程序会和预期不符,因此要消除二义性
复制代码
内联函数,能够避免函数调用的开销,不会进入到函数的地址区,而是经过编译器直接将函数代码"粘贴"到对应位置,因此不适用于大型的函数,只适用于小型的,频繁调用的函数。
inline int f(int a,int b) {return a>b?a:b;}
cout<<f(1,2)<<endl;
//等价于
cout<<1>2?1:2<<endl;
复制代码
assert预处理宏
assert(expr)
//表达式为假则输出信息并终止程序的运行
//为真则什么也不作
复制代码
具体操做以下
void f();
void f(int);
void f(int,int);
void f(double,double=3.14);
f(5.6);
(1)肯定候选函数
1.与被调用的函数重名
2.其声明在调用点可见
//无淘汰
(2)肯定可行函数
1.形参数量与本次调用提供的实参数量相等(考虑默认参数但是可行的)
2.每一个参数的类型与对应的形参类型相同,或者能转换成形参类型
//淘汰第1,3
//若是这步未找到可行函数,编译器会报无匹配函数错误
(3)寻找最佳匹配
寻找形参类型与实参类型最匹配的那个函数
最佳匹配等级:
1.精确匹配
实参类型和形参类型相同
实参从数组类型或函数类型转换成对应的指针类型
向实参添加顶层const或者从实参中删除顶层const
2.经过const转换实现匹配(底层const)
3.经过类型提高实现的匹配
4.经过算术类型转换或指针转换实现的匹配
5.经过类类型转换实现的匹配
(若是重载函数的区别只是多了个底层const的话,将从函数调用的实际参数类型(常量或者很是量)来判断)
多个形参的函数匹配
1.该函数每一个实参的匹配都不劣于其余可行函数须要的匹配
2.至少有一个实参的匹配优于其余可行函数提供的匹配
若是检查了以后没有找到惟一的一个函数脱颖而出,则编译器报告二义性调用的信息。
//f(42,2.56)
//典型的二义性错误
复制代码
函数指针指向的是函数不是对象。
int max(int a,int b);
//声明一个能够指向该函数的指针,只须要用指针替换函数名便可
int (*p)(int ,int);
//将函数赋值给函数指针的时候能够忽略取地址符
p=max;
p=&max; //加不加都同样
//调用函数指针指向的函数的时候用不用解引用指针也同样
cout<<p(1,2)<<endl;
cout<<(*p)(1,2)<<endl;
//能够为函数指针赋值0或者nullptr表示没有指向任何位置
//当使用重载函数的时候,上下文必须清晰的界定到底使用的是哪一个函数,不能够一对多
复制代码