C++ lambda表达式
https://msdn.microsoft.com/zh-cn/library/dd293608.aspx
lambda表达式是C++11的标准。如果用的是g++,记得加参数。
lambda表达式在其所在的位置上定义了一个匿名函数对象。
先给个例子:
#include <algorithm> #include <cmath> void abssort (float *x, unsigned n) { std::sort (x, x + n, //Lambda 表达式 [](float a, float b) { return (std::abs(a) <std::abs(b)); } ); }
以下时来自微软官网的解释:
1、捕获子句(lambda表达式从此处开始,也叫做lambda-introducer。)(14标准)
捕获子句指定了哪些变量可以被捕获,以及捕获的形式(值还是引用)。捕获的是lambda表达式所在的封闭作用域中。
如果[]里为空,表示任何变量都不会传递给lambda表达式。
[=]表示默认按值传递,[&]表示默认按引用传递。[var]:var是变量名,前面可以添加&前缀,表示var变量按引用传递。
[&total, factor] //total 按引用传进来,factor则是按值传递 [&, factor] //默认引用 [=, &total] //默认传值 [=, total] //出错,原因:重复。默认按值,total也是按值,此时可以将total省略掉 [=, this] //同样的原因出错,有人可能会认为this是指针。但要记住指针和引用不同,指针本身同样是按值传递的。
C++14标准中还允许在捕获子句中创建并初始化新的变量,如:
pNums = make_unique<vector<int>>(nums); auto a = [ptr = move(pNums)]() { //use ptr };
2、参数列表(可选,也叫做lambda声明符(lambda declarator)
接收输入参数,如果参数类型是通用的,可以选择auto关键词作为参数类型(模版)。
auto y = [] (auto first, auto second) { return first + second; };
因为lambda表达式可以作为右值赋值给变量,所以也可以作为参数传递给lambda的参数列表。3、mutable 选项(可选)
加上mutable后,lambda表达式体内的语句可以修改按值捕获的变量。
4、异常选项(可选)
加上throw()表示lambda表达式不抛出任何异常(别搞反了),下面的代码会出错的
//windows 环境下使用cl编译器
//compile with:/W4 /EHsc
int main() //C4297 expected { [] () throw {throw 5;}(); }
5、尾部返回类型(trailing-return-type) (可选)
一般来讲lambda表达式的返回值都可以由编译器自动猜测除非你指明了尾部返回类型。
6 lambda 本体
int main() { int m = 0; int n = 0; [&, n] (int a) mutable { m =++n + a; } (4); cout << m << endl <<n <<endl;
}
output:
5
0
4是通过参数列表里的a传进。默认为引用所以m的修改会影响外面的值。虽然加了mutable,但是n修改的只是副本,如果不加mutable,会报错。