一. lambda表达式
- 形式
- lambda表达式也称为匿名函数,是c++11最常用的也是最重要的一个特性之一,优点就是不需要额外定义一个函数;
- 语法形式
[capture](params)opt->res{body};
其中capture为捕获列表,params为参数列表,opti表示函数选项(可不写),res为返回值类型(可以不写),body是函数体。
auto fun=[](int a,int b){return a+b;};
- 捕获列表的介绍
[] 不捕获任何变量
[&] 捕获外部作用域中所有变量,并作为引用在函数体中使用;
[=] 捕获外部作用域中所有变量,并作为副本在函数体中使用。
[&a] 按引用捕获变量a;
[a] 按值捕获变量a.
[=,&a] 按值捕获作用域中除了a的所有变量,对a按引用捕获。
[&,a] 按引用捕获初a所有变量,对a按值捕获;
[this] 捕获当前类中的指针。 - 由于lambda表达式的函数默认为const,因此对外部获取的变量不可修改,如果需要修改,可在opt处加上mutable
int a=10;
auto fun=[&]()mutable{a++; };
fun();
cout<<a<<endl;// 输出a为11.
auto fun2=[=]()mutable{a++; };
fun2();
cout<<a<<endl;// 输出a还是为11.
- 上述中捕获列表的不同,导致a的值也不同。第一个捕获列表表示以引用方式捕获外部所有变量,因此内部对a的值改变后,改变会保留;而第二个捕获列表是以传值的方式捕获外部变量,相当于a的一个副本,因此内部对a的值改变后,并不影响外界a的值。
- 适应场景
(1) 简单函数,无需额外定义
int data[6]={1,5,2,6,3};
sort(data,data+6,[](int a,int b){return a>b;});//最后的函数为自定义的比较函数,这样就会降序排列
(2) 使用auto接受一个lambda表达式,这样lambda可以复用
int a = 10;
auto fun = [&](int tmp) {return tmp * a; };
cout << fun(4) << endl;//输出40
(3) 利用lambda实现递归
(4) 对于需要重复调用的相同代码块,但代码块中函数变量不同,如果使用函数调用,那么需要将多个参数都传给函数,当参数数目变化时,需要重新修改函数。利用lambda表达式可以避免这种情况
void testFun(){
int a,b,c;
if(条件1,para1){
//使用a,b,c,para1的代码块,
}
if(条件2,para2){
//使用a,b,c,para2的代码块,
}
if(条件3,para3){
//使用a,b,c,para3的代码块,
}
}
修改为
void testFun(){
int a,b,c;
auto fun=[=](int para){
//包含a,b,c, para的代码块
}
if(条件1,para1){
fun(para1);
}
if(条件2,para2){
fun(para2);
}
if(条件3,para3){
fun(para3);
}
}
二、c++ 三目运算符
- 语法格式
条件? 语句1: 语句2
- 适应场景:(1)条件赋值;(2)条件执行
int a = 10;
int b = 10;
bool symbol = (a == b) ? true : false;
cout << symbol << endl;
(symbol==true)?a=11 :a=12;
三、仿函数
四、内联函数
- 使用场景
函数在调用和执行时是需要耗费时间的,如果一个函数本身语句很少,执行时间很短,那么函数调用产生的额外开销与函数本身执行的时间相比,就不能忽略了,假如这个函数在一个循环中被上千万次调用,函数调用导致的时间开销会使程序运行变得缓慢。此时就可以利用inline函数解决, inline函数与普通函数语法上区别只有前面加了一个inline
inline int MAX(int a, int b){
if(a<b){return a;}
else{
return b;
}
}
- 禁用场景
(1)内联函数就是以空间获取时间,如果函数本身很复杂,执行时间远大于调用时间,那么再使用内联函数,就会使得代码体积增加不少代价。
(2)如果内联函数本身代码不复杂,但因为内部存在循环,导致执行时间远大于调用时间,那么此时也不适用。