lamda表达式
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
lamda表达式可以看作是一个匿名函数。编译器在编译的时候会将lamda表达式处理成一个仿函数类类名是类名是不重复的随机名称因为一个作用域中可能存在多个仿函数返回该仿函数的对象。
lamda既然可以看作是一个匿名函数那就至少具备除函数名以外的两部分返回值、形参列表、函数体
lamda表达式的书写格式
[capture-list](parameters)mutable->return-type{ statement }
/*
[](const int x, const int y)mutable->int{
return x + y;
}
*/
目录
一、lamda表达式各部分说明
1、capture-list必要部分
(1) 捕获方式
capture-list表示捕获列表lamda表达式可以通过捕获列表来获取上下文的变量以供lamda表达式使用无需通过形参列表传递变量。
捕获列表有两种方式来捕获变量值传递、引用传递
捕获方式 | 解释 |
[var] | 以值传递的方式捕获变量 var如[ a ]捕获上下文中的变量a |
[=] | 以值传递的方式捕获父作用域中的所有变量包括this |
[&var] | 以引用传递的方式捕获变量var |
[&] | 以引用传递的方式捕获父作用域中的所有变量包括this |
[this] | 以值传递的方式捕获当前的this指针 |
(2) 注意事项
不能以相同的方式捕捉同一个变量。比如[=, a] = 表示以传值的方式捕捉所有的变量(包括变量a)a表示以传值的方式捕捉变量a这个时候变量a以传值的方式被捕捉了两次
[=, a](){} // 错误重复捕获
不能捕捉父作用域之外的变量包括全局变量
int a = 10;
auto obj1 = []{}; // 注意此时lamda表达式没有父作用域捕获列表必须为空
int main()
{
auto obj2 = [a]{}; // 错误不可以捕获全局变量
}
lamda表达式不能相互赋值。lamda表达式底层是被处理成一个类不同的lamda表达式相当于不同的类即便是类型相同也不行不同的类之间不能相互赋值。
int main() {
auto obj1 = [] {};
auto obj2 = [] {};
obj2 = obj1; // 错误obj1和obj2底层被处理成不同的类他们的类名不可能重复
}
2、parameters可选部分
parameters表示调用lamda表达式时要传递给lamda表达式的值。如果无需传递参数该部分可以省略。
[]mutable->int{ return 0; };
3、mutable可选部分
默认情况下lambda函数总是一个const函数mutable可以取消其常量性。使用该修饰符时参数列表parameters不可省略即使参数为空
[]()->int{ return 0; };
4、->return-type可选部分
return-type表示lamda表达式的返回值类型。无返回值时可以省略有返回值时也可以省略此时交由编译器推导。
[](){ return 0; };
5、 statement必要部分
statement表示函数体在函数体中可以使用形参列表也可以使用所有捕获到的变量函数体中的语句可以有多条。
int main()
{
int a = 10;
auto obj = [&a](const int x){
int c = x - a;
return c;
};
return 0;
}
二、lamda表达式的底层处理
以下面这个lamda表达式为例
int main() {
auto obj1 = [] {};
obj1();
cout << typeid(obj1).name() << endl;
}
由此可见lamda表达式实际上是被处理成一个类类名是 lamda_<uuid> 这样保证了每个lamda表达式的唯一性。lamda表达式的返回值就是该类的对象。
我们通过反汇编来看一下lamda表达式的调用过程我们会发现类lamda_<uuid> 中重载了operator()这样就可以使用对象来调用lamda表达式了。