声明Lambda
Lambda表达式完整的声明格式如下
[capture list] (params list) mutable exception-> return type { function body }
各项具体含义如下
- capture list:捕获外部变量列表
- params list:形参列表
- mutable指示符:用来说用是否可以修改捕获的变量
- exception:异常设定
- return type:返回类型
- function body:函数体
此外,我们还可以省略其中的某些成分来声明“不完整”的Lambda表达式,常见的有以下几种:
序号 | 格式 |
---|---|
1 | [capture list] (params list) -> return type {function body} |
2 | [capture list] (params list) {function body} |
3 | [capture list] {function body} |
lambda
表达式最前面的方括号的意义何在?其实这是lambda
表达式一个很要的功能,就是闭包。这里我们先讲一下lambda
表达式的大致原理:每当你定义一个lambda
表达式后,编译器会自动生成一个匿名类(这个类当然重载了()
运算符),我们称为闭包类型(closure type)。那么在运行时,这个lambda
表达式就会返回一个匿名的闭包实例,其实一个右值。所以,我们上面的lambda
表达式的结果就是一个个闭包。闭包的一个强大之处是其可以通过传值或者引用的方式捕捉其封装作用域内的变量,前面的方括号就是用来定义捕捉模式以及变量,我们又将其称为lambda
捕捉块。
捕获其所在作用域中的变量:
- []:默认不捕获任何变量;
- [=]:默认以值捕获所有变量;
- [&]:默认以引用捕获所有变量;
- [x]:仅以值捕获x,其它变量不捕获;
- [&x]:仅以引用捕获x,其它变量不捕获;
- [=, &x]:默认以值捕获所有变量,但是x是例外,通过引用捕获;
- [&, x]:默认以引用捕获所有变量,但是x是例外,通过值捕获;
- [this]:通过引用捕获当前对象(其实是复制指针);
(1)[x] 表示值传递方式捕捉变量
int a = 123;
auto f = [a] { cout << a << endl; };
f(); // 输出:123
//或通过“函数体”后面的‘()’传入参数
auto x = [](int a){cout << a << endl;}(123);
(2)[&x]:仅以引用捕获x,其它变量不捕获;
int a = 123;
auto f = [&a] { cout << a << endl; };
a = 321;
f(); // 输出:321
(3)[=]:默认以值捕获所有变量;
int a = 123;
auto f = [=] { cout << a << endl; }; // 值捕获
f(); // 输出:123
(4)[&]:默认以引用捕获所有变量;
int a = 123;
auto f = [&] { cout << a << endl; }; // 引用捕获
a = 321;
f(); // 输出:321
(5)[=, &x]:默认以值捕获所有变量,但是x是例外,通过引用捕获;
int a = 1,b =2, c =3;
auto f = [=,&a,&b]()
{
cout << a << b << c << endl;// 输出 1 2 3
//c = 30; 修改c会报错error: assignment of read-only variable
a = 10;
b = 20;
cout << a << b << c << endl;// 输出 10 20 3
};
(6)[&, x]:默认以引用捕获所有变量,但是x是例外,通过值捕获;
int a = 1,b =2, c =3;
auto f = [&c,a,b]()
{
cout << a << b << c << endl;// 输出 1 2 3
c = 30; 修改a,b会报错error: assignment of read-only variable
cout << a << b << c << endl;// 输出 1 2 30
};