C++11 Lambda表达式 木灵的炼金工作室

C++11引入了一个新的特性:Lambda表达式。
Lambda表达式可以理解为一种内联的函数,它在一些函数指针传递过程中格外便利(如for_eachsort)。

语法

[/Cl] (/Pl) mutable throw(/Ex)->/RT {/bd}
这么看可能有点恐怖,举个例子:

[&](string &temp)->void {
    for (int i = 0; i < temp.length() / 2; i++) {
        swap(temp[i], temp[temp.length() - 1 - i]);
    }
});

分解:

  1. /Cl指捕获模式,[/Cl]称为捕获子句,它指出了Lambda函数体对于外部作用域内变量的默认访问模式。它可以有如下几种写法:
    1. & = 一般地,表示默认以引用/传值方式获取外部作用域内的全部变量
    2. &NAME NAME 特殊地,表示以引用/传值方式获取外部作用域内名称为NAME的变量
    3. this 以传值方式获取this指针 上述三种写法允许以任意顺序组合:比如[&, x, y]表示变量x和y以传值方式获取,其余变量均以引用方式获取
      在C++14中,你可以在捕获模式中以外部变量初始化Lambda内部的变量
      需要注意的是,捕获子句中通过传值捕获的变量将默认为const
    4. 特殊地,如果将/Cl置空,则表示不获取任何外部作用域中的变量
  2. /Pl是参数列表,这个很直观。有的时候会作为仿函数接口来使用(比如上述例子)。
  3. mutable是可变规范,可选。刚刚我们说过,捕获子句中通过传值捕获的变量将默认为const,那么mutable就是为了解除这一限制的。将Lambda声明为mutable就可以修改传值变量。
  4. throw(/Ex)是异常规范,可选。这个也很直观。允许使用noexcept关键字。
  5. ->/RT是返回类型,可选。C++默认以auto推导返回类型,所以说这一项省略也无所谓。
  6. /bd是函数体,不可选。
  7. 你可以在Lambda的尾端加上()来原地调用它:

    []() { std::cout << "Hello World"; } ()
    
  8. 如希望为Lambda指定函数名,你需要以下的方式:

    auto functionName = []() { std::cout << "Hello World"; };
    

    这实际上是声明了一个函数指针。一般我们使用auto自动推导指针的类型。

    当然,匿名函数也是允许的,一般用在函数指针的传值中(如for_each中):

    for_each(words.begin(), words.end(), [&](string &temp)->void {
         for (int i = 0; i < temp.length() / 2; i++) {
             swap(temp[i], temp[temp.length() - 1 - i]);
         }
     });
    


Copyright AmachiInori 2017-2021. All Right Reserved.
Powered By Jekyll.
amachi.com.cn