有些算法只是接受一元谓词或者二元谓词,但是我们希望传入更多的参数,这时候纪要借助lambda表达式了。lambda表达式相当于是一个没有名字的函数,其具体的形式为:
[capture list](parameter list)->return type{function body}
lamda表达式一般用于传入谓词的情况,这样就无需在重新写函数进行调用,而且lambda表达式可以定义在函数内部。
举例:
vector<int>ve={1,3,4,6,5,8};
for_each(ve.begin(), ve.end(), [](int a){cout<<a<<endl;});//打印ve的所有元素到终端
//不用于谓词的情况
auto c=[](int a,int b)->int{return a + b;};
cout << c(5,6) << endl;//lamda表达式的调用方式。
我们在使用时可以省略参数列表和返会值类型。
1.参数的传递
[capture list](parameter list)->return type{function body}
(parameter list)
中就是传入到lamda表达式中的参数,和函数的传参类似,如果传入的参数仅仅是传的值,那么在lambda表示内部就会拷贝临时变量,lambda内部对值的改变不会影响全局的变量值。但是传入引用或者指针则会相应的修改全局的变量的值。
auto c=[](int &a,int &b){//传入值将不会改变全局中的变量的值
a = 1;
b = 2;
return;
};
auto c=[](int &a,int &b){//传入引用或者指针将会改变全局中的变量的值
a = 1;
b = 2;
return;
};
参数的传递如果不需要改变全局数据一般建议传入的是值或者是const &。
2.捕获列表[capture list]
对于lambda表达式而言,它是没法直接使用全局变量的,它使用的全局变量之只能是捕获列表中的捕获了的变量。
string a="hello";
auto c=[](int &a,int &b){
a = 1;
b = 2;
cout<<c<<endl;//这行语句将会报错,因为c没有被捕获
return;
};
string a="hello";
auto c=[c](int &a,int &b){
a = 1;
b = 2;
cout<<c<<endl;//正确,c在捕获列表中,可以使用。
return;
};
捕获的方式有两种,一种是显式捕获,另一种是隐式捕获。
显式捕获
显式捕获就是在参数列表中直接添加需要捕获的变量的名字,并用“,”隔开。显示捕获有两种方式,值捕获和引用捕获。
值捕获
所谓值捕获就是说捕获的为全局变量的值,在lambda表达式的局部内对这个值的改变将会报错。
引用捕获
值捕获没法改变全局变量的值,所以我们可以采用引用捕获的方式来进行捕获,这样捕获的参数将会改变全局变量的值。
int a=0;
int b = 5;
auto c=[a,&b](){//值捕获a,引用捕获b
a = 1;//报错,a不是说可以修改的左值
b = 2;//正确,可以修改引用捕获的全局变量
return;
};
隐式捕获
显示捕获可以让编译器自己推断我们需要捕获的变量或者对象,我们用 [=] 表示我们采用的是值捕获的方式,用 [&] 表示我们将采用引用捕获的方式。采用显示捕获的方式就不需要在指定每一个我们想要捕获的变量了,lambda会自己帮我们捕获,我们直接使用就可以了。
auto c=[=](){//显示值捕获
........
return;
};
auto c=[&](){//显示引用捕获
........
return;
};
我们使用lambda表达式的时候也可以采用显示和隐式混合的捕获方式,采用混合的捕获方式捕获列表中的第一个值一定是“=”或者“&”。
下表是lambda的所有的捕获方式。
3.返回值
当我们需要指定lambda的返回类型的时候,我们就必须指定其返回的数据类型,而且必须采用后置返回的方式进行返回。
auto c=[=]()->int {
return 10;
};
返回类型int不能省略,后置返回符号“->”不能省略。