捕获列表,只用于局部非static变量,lambda可以直接使用局部static变量和它所在函数之外声明的名字。
eg:
1 #include<iostream> 2 using namespace std; 3 4 int main() 5 { 6 auto f= [ma] (int a){return a>ma; }; 7 cout << f(9) << endl; 8 return 0; 9 }
捕获ma,但是ma并未在使用lambda之前并未定义一个局部的ma,故上诉代码报错。
eg:
1 #include<iostream>
2 using namespace std;
3 int ma = 10;
4 int main()
5 {
6 auto f= [] (int a){return a>ma; };
7 cout << f(9) << endl;
8 return 0;
9 }
此时在外部定义全局变量ma,lambda不用捕获列表,依旧可以在表示内使用ma。
当定义一个lambda时,编译器生成一个与lambda对应的新的(未命名)类类型。
目前,可以先这样理解:当向一个函数传递一个lambda时,同时定义了一个新类型和该类型的一个对象:传递的参数就是此编译器生成的类类型的未命名对象。类似的,当使用auto定义一个用lambda初始化的变量时,定义了一个从lambda生成的类型对象。默认情况下,从lambda生成的类都包含一个对应该lambda所捕获的变量的数据成员。类似任何普通类的数据成员,lambda的数据成员也在lambda对象创建时初始化。
类似参数传递,变量的捕获方式可以是值或引用。与传值参数类似,采用值捕获的前提是变量可以拷贝。与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时。
eg:
1 #include<iostream>
2 using namespace std;
3
4 int main()
5 {
6 int ma = 10;
7 auto f= [ma] {return ma; };
8 ma = 1;
9 cout << f() << endl;
10 return 0;
11 }
输出10。
引用捕获:
1 #include<iostream> 2 using namespace std; 3 4 int main() 5 { 6 int ma = 10; 7 auto f= [&ma] {return ma; }; 8 ma = 1; 9 cout << f() << endl; 10 return 0; 11 }
此时输出 1。如果我们采用引用方式捕获一个变量,就必须确保被引用的对象在lambda执行的时候是存在的。lambda捕获的都是局部变量,这些变量在函数结束后就不复存在了。如果可能的话,尽量避免捕获指针或者引用。