[C++] Lambda表达式使用说明

前言:

c++ 11引入了Lambda表达式,即匿名函数,此语法极大地削减了某些场景下的代码量。Lambda表达式是一个可执行对象,功能类似于函数,但是存在于函数内部,且仅能在函数内部访问。

语法:

[捕获列表](入参列表)[->返回值类型]{函数体}

捕获列表不可为空;

入参可为空;

返回值为空;

函数体不可为空;

例如:

auto f  = []{return 40;}

auto f1 = [](int i)->int{ return i*10; }

限制:

Lambda定义在函数内,也只能使用函数内的局部变量,而且不是所有的都能用,只能用那些作为捕获列表传递给自己的。

例如:

void func()

{
    int i;
    string s;
    char c;

    auto f = [i,s]{
        //lambda body
        printf("s is -> %s",s.c_str());
        printf("i is -> %d",i);
        //printf("c is -> %c",c);        //这里不能用c,因为c不在捕获列表中
    }

}

底层原理:

Lambda的底层原理是一个匿名类:

  • 这个类使用捕获列表中的数据类型创建自己的成员变量;
  • 再重载operator()运算符,即让自己是一个可调用类,operator()运算符的实现就是Lambda的函数体;
  • 参数列表为operator()运算符的入参,即上一步中重载运算符的参数列表和入参列表一致;
  • 同理,返回值类型便是operator()运算符的返回值类型。

ps:捕获列表可以不按值传递,可以传引用和指针。

既然可以使值捕获,也可以是引用捕获,那么如果是值捕获模式,那么要求捕获列表中参数的类型一定是有拷贝构造的,这也是类类型作为函数入参的必要条件。

隐式捕获和全捕获列表:

如果Lambda所处的函数中有很多局部变量,而这些变量全都要在Lambda中捕获使用,那么是不是就必须把这些变量全都写到捕获列表中了呢?这样的话岂不是会写很长的捕获列表?

答案是否定的,我们可以通过隐式捕获的方式指定当前函数的所有局部变量都可以在Lambda中使用,语法如下:

auto f = [=]{ return true; }           //f所处函数中的所有局部变量都按照 值传递 的方式作为Lambda的捕获列表

auto f = [&]{ return true; }           //f所处函数中的所有局部变量都按照 引用传递 的方式作为Lambda的捕获列表

问题又来了,如果想让个别局部变量区别于其他的捕获方式呢?比如其他局部变量都是 值捕获, 但是局部变量 c 希望是引用捕获,那么就有:

void fun (){

       int i,j,k,l,d,m,f;

       char c;

       auto f = [=,&c] {

             int total = i+k+j+l+d+m+f;           //可以使用所有局部变量

             c = 'A';              //改变fun函数的局部变量c,因为是引用捕获,所以会影响原值
       }
}

同理,有:

auto f = [&,c] { ... }              //所有局部变量都是引用捕获,仅c为值捕获

结语:

lambda的初衷是用来替代 容器泛型算法的。

猜你喜欢

转载自blog.csdn.net/ykun089/article/details/106982966
今日推荐