# [C++11 带来的新特性 (4)—— 匿名函数(Lambdas)](https://www.cnblogs.com/sword03/p/10022964.html) ## 1 语法 Lambdas并不是新概念,在其它语言中已经烂大街了。直接进入主题,先看语法: ``` [ captures ] ( params ) specifiers exception attr -> ret { body } (1) [ captures ] ( params ) -> ret { body } (2) [ captures ] ( params ) { body } (3) [ captures ] { body } (4) ``` - captures:捕获参数。详细格式见下图。 | 格式 | 意义 | | ------- | ----------------------------------------------- | | [] | 默认不捕获任何变量 | | [=] | 默认以值捕获所有变量 | | [&] | 默认以引用捕获所有变量 | | [x] | 仅以值捕获x,其它变量不捕获 | | [&x] | 仅以引用捕获x,其它变量不捕获 | | [=, &x] | 默认以值捕获所有变量,但是x是例外,通过引用捕获 | | [&, x] | 默认以引用捕获所有变量,但是x是例外,通过值捕获 | | [this] | 通过引用捕获当前对象(其实是复制指针) | | [*this] | 通过传值方式捕获当前对象 | - params:参数列表。 - ret:返回类型。 - body:函数体。 - specifiers:限定符列表。比如mutable。 - exception:异常规定。比如noexcept。 - attr:属性规定,[详见](https://zh.cppreference.com/w/cpp/language/attributes)。 ## 2 使用 Lambdas重在使用,所以下面直接上实例,由浅入深的介绍使用方法。 ### 2.1 打印字符串 - 定义一个匿名函数 ``` []{ std::cout<< "hello world!" < double{ return 42; } ``` 等价于 ``` []{ return 42; } ``` 如果不指定返回类型,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 < vec = { 1, 2, 3, 4, 5 }; double total = 0; //inclucde 'algorithm' for foreach std::foreach(begin(vec), end(vec), [&](int x) { total += x; }); std::cout<<"total:"<< total < points; for( auto i = 0; i < 10 ; i++ ) points.push_back(Point()); cout<<"Unsorted:"< bool{ return (a.x * a.x) + (a.y * a.y) < (b.x * b.x) + (b.y * b.y); }); cout<<"Sorted:"< std::function returnLambda (){ return [](int x, int y){ return x*y; }; } auto lf = returnLambda(); std::cout<< lf(6,7) << std::endl; ``` ### 2.8 奇怪的捕获变量作用域 ``` void PerformOperation( function f ){ f(); } int main(){ int x = 100; auto func = [&](){ x++;}; PerformOperation(func); std::cout<< "x:" << x << std::endl; return 0; } ``` 输出: ``` x:101 ```