C++ 中关于Lambda 表达式的总结

Lambda表达式是C++ 11新特性之一,总的来说就是一个函数,第一眼看到这个函数也是一脸懵逼,怎么没有见到过这个写法?于是查找了一些资料,按照我的理解记录一下

Lambda基本语法

Lambda标准语法定义:

[capture] (parameters) mutable ->ret-type{body};

说明:

  • 1.[capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。实际上,[]是Lambda引出符。编译器根据该引出符判断接下来的代码是否是Lambda函数。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用,捕获列表可以是下面的类型:

    • 1.[var]表示值传递方式捕捉变量var;

    • 2.[=]表示值传递方式捕捉所有父作用域的变量(包括this);

      auto f1 = [=]{return a + 1;};    //按值捕获a
    • 3.[&var]表示引用传递捕捉变量var;

    • 4.[&]表示引用传递方式捕捉所有父作用域的变量(包括this);

      auto f2 = [&]{return a + 1;};    //按引用捕获a
    • 5.[this]表示值传递方式捕捉当前的this指针。

    • 6.[ ]表示不捕获任何变量。

    捕获列表也可以组合:

    • 1.[=,&a,&b]表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量;
    • 2.[&,a,this]表示以值传递的方式捕捉变量a和this,引用传递方式捕捉其它所有变量。

    如果重复是不允许的:

    • 1.[=,x]这里已经以值传递方式捕捉了所有变量,但重复捕捉x;

    • 2.[&,&this]&已经相当于以引用传递方式捕捉了所有变量,再捕捉this则会重复。

  • 2.(parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略;

  • 3.mutable:mutable修饰符。默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空);

  • 4.->ret-type:返回类型。可以指定,也可以不指定,不指定编译器则会自动推导返回类型,例如:

    [](double x ) {int y = x ;};

    如果函数有多个返回值,编译器不能推导,需要自行添加,例如:

    [](double x )->double{int y = x ;return x - y;};
  • 5.{body}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

Lambda函数具体使用

1.其中上面讲到了父作用域,简单来说就是包含Lambda函数的{ }代码段。

2. 另外,Lambda是匿名函数,但通常会给它取名,例如:

auto f = [](int x ) {return x % 3 ==0;};

这样就可以在程序中更方便的调用Lambda函数了:

#include 
using namespace std;
int main()
{
    int a = 10, b = 5;
    auto f = [=]{return a + b;};   //[=]按值捕获了a和b
    cout << f() << endl;         //值为15
    return 0;
}

3.保持Lambda函数引用的变量的值是最新的:

#include 
using namespace std;
int main()
{
    int a = 8;
    auto f1 = [=]{return a + 1;};  //按值捕获a
    auto f2 = [&]{return a + 1;};  //按引用捕获a
    cout << f1() << endl;
    cout << f2()<< endl;
    a++;
    cout << f1() << endl;
    cout << f2() << endl;
    return 0;
}

程序结果:
    8
    8
    8
    9

按值捕获可以看作Lambda函数生成了一个const类型的变量,它的值是不会因为外部更新而更新的;同样引用捕获相当于调用a的内存地址,保证实时更新,如果想要Lambda函数在调用时访问的外部变量是最新的,我们就需要使用按引用捕获。

如果非要做到修改值捕获变量的值,就可以使用mutale关键字;默认情况下,lambda函数是一个const函数,而mutable也可以取消常量性,例如:

#include 
using namespace std;
int main()
{
    int a = 10;
    auto f = [=]()mutable{return a *= 10;};//取消常量性
    cout << f() << endl;
    return 0;
}

程序结果:
    100

mutable 修饰的 Lambda 表达式就算没有参数也要写明参数列表,这里的()表示没有省略,只是没有参数而已。


   转载规则


《C++ 中关于Lambda 表达式的总结》 Tyzhao 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录