1 语法
Lambdas并不是新概念,在其它语言中已经烂大街了。直接进入主题,先看语法:
1[ captures ] ( params ) specifiers exception attr -> ret { body } (1) 2[ captures ] ( params ) -> ret { body } (2) 3[ captures ] ( params ) { body } (3) 4[ captures ] { body } (4) 5
- captures:捕获参数。详细格式见下图。
格式
意义
[]
默认不捕获任何变量
[=]
默认以值捕获所有变量
[&]
默认以引用捕获所有变量
[x]
仅以值捕获x,其它变量不捕获
[&x]
仅以引用捕获x,其它变量不捕获
[=, &x]
默认以值捕获所有变量,但是x是例外,通过引用捕获
[&, x]
默认以引用捕获所有变量,但是x是例外,通过值捕获
[this]
通过引用捕获当前对象(其实是复制指针)
[*this]
通过传值方式捕获当前对象
- params:参数列表。
- ret:返回类型。
- body:函数体。
- specifiers:限定符列表。比如mutable。
- exception:异常规定。比如noexcept。
- attr:属性规定,详见。
2 使用
Lambdas重在使用,所以下面直接上实例,由浅入深的介绍使用方法。
2.1 打印字符串
-
定义一个匿名函数
[]{ std::cout<< "hello world!" <<std::endl; }
-
调用匿名函数
[]{ std::cout<< "hello world!" <<std::endl; }();
-
传递匿名函数给一个变量
auto l = []{ std::cout<< "hello world!" <<std::endl; }; l();
2.2 带参数列表的匿名函数
1auto l = [](const std::string &s){ 2 std::cout<< s <<std::endl; 3}; 4l("hello world!");
2.3 指定返回值类型的匿名函数
1[] -> double{ 2 return 42; 3}
等价于
1[]{ 2 return 42; 3}
如果不指定返回类型,C++11也可以自动推断类型。
2.4 带捕获参数的匿名函数
-
捕获变量值+捕获变量引用
int x = 0; int y = 42; auto f = [x, &y] { std::cout<<"x:" << x << std::endl; std::cout<<"y:" << y << std::endl; ++y; //++x;//Error }; x = y = 77; f(); f(); std::cout<< "final y: " << y <<std::endl;
输出
1x:0 2y:77 3x:0 4y:78 5final y: 79
-
捕获所有变量值
int x = 0; int y = 42; auto f = [=] { std::cout<<"x:" << x << std::endl; std::cout<<"y:" << y << std::endl; //++y;//Error //++x;//Error }; x = y = 77; f(); f(); std::cout<< "final y: " << y <<std::endl;
输出
1x:0 2y:42 3x:0 4y:42 5final y: 77
-
捕获所有变量引用
int x = 0; int y = 42; auto f = [&] { std::cout<<"x:" << x << std::endl; std::cout<<"y:" << y << std::endl; ++y;//Error ++x;//Error }; x = y = 77; f(); f(); std::cout<< "final x: " << x <<std::endl; std::cout<< "final y: " << y <<std::endl;
输出
1x:77 2y:77 3x:78 4y:78 5final x: 79 6final y: 79
2.5 使用匿名函数统计容器中所有元素的值之和
1std::vector<int> vec = { 1, 2, 3, 4, 5 }; 2double total = 0; 3 4//inclucde 'algorithm' for foreach 5std::foreach(begin(vec), end(vec), 6 [&](int x) { 7 total += x; 8 }); 9std::cout<<"total:"<< total <<std::endl;
输出:
total:15
2.6 使用匿名函数对容器中的元素排序
1struct Point{ 2 double x,y; 3 Point(){ 4 x = (rand() % 10000) - 5000; 5 y = (rand() % 10000) - 5000; 6 } 7 8 void Print(){ 9 std::cout<<"["<<x<<","<<y<<"]"<<std::endl; 10 } 11}; 12 13 14int count = 10; 15std::vector<Point> points; 16for( auto i = 0; i < 10 ; i++ ) points.push_back(Point()); 17 18cout<<"Unsorted:"<<endl; 19for( auto i = 0; i < 10 ; i++ ) points[i].Print(); 20 21std::sort(points.begin(), points.end(), 22 [](const Point& a, const Point& b) -> bool{ 23 return (a.x * a.x) + (a.y * a.y) < (b.x * b.x) + (b.y * b.y); 24 }); 25cout<<"Sorted:"<<endl; 26for( auto i = 0; i < 10 ; i++ ) points[i].Print();
输出:
1Unsorted: 2[4383,-4114] 3[-2223,1915] 4[2793,3335] 5[386,-4508] 6[1649,-3579] 7[-2638,-4973] 8[3690,-4941] 9[2763,-1074] 10[-4460,-1574] 11[4172,736] 12Sorted: 13[-2223,1915] 14[2763,-1074] 15[1649,-3579] 16[4172,736] 17[2793,3335] 18[386,-4508] 19[-4460,-1574] 20[-2638,-4973] 21[4383,-4114] 22[3690,-4941]
2.7 返回匿名函数类型
1//include<functional> 2std::function<int(int,int)> returnLambda (){ 3 return [](int x, int y){ 4 return x*y; 5 }; 6} 7 8auto lf = returnLambda(); 9std::cout<< lf(6,7) << std::endl;
2.8 奇怪的捕获变量作用域
1void PerformOperation( function<void()> f ){ 2 f(); 3} 4 5int main(){ 6 int x = 100; 7 auto func = [&](){ x++;}; 8 PerformOperation(func); 9 std::cout<< "x:" << x << std::endl; 10 return 0; 11}
输出:
x:101