c++11特性之Lambda表达式

更多c++后台开发相关知识,可以看我的博客:https://blog.csdn.net/ypshowm

一个lambda表达式表示一个可调用的代码单元。与函数一样,也具有一个返回类型,一个参数列表,和有一个函数实体。

表达式如下:

[capture list] (params list) mutable exception-> return type { function body }

各项具体含义如下

  1. capture list:捕获外部变量列表(捕获的是lambda所在函数中定义的局部变量的列表,通常为空)
  2. params list:形参列表
  3. mutable指示符:用来说用是否可以修改捕获的变量
  4. exception:异常设定
  5. return type:返回类型(lambda必须使用尾置类型返回)
  6. function body:函数体。

我们可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体。

如下几种缩写:

1 [capture list] (params list) -> return type {function body}
2 [capture list] (params list) {function body}
3 [capture list] {function body}

lambda与普通函数的不同:

        lambda不能有默认单数,一个lambda调用的实参数目永远与形参数目相等。

一个lambda只能在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数体中使用该变量。

捕获列表只用于局部非static变量。

值捕获

与传值参数类似,采用值捕获的前提是变量可以拷贝。与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝:

void fcn()
{
    size_t v1 = 42;    //局部变量
    //将v1拷贝到名为f的可调用对象
    auto f = [v1] {return v1;};
    v1 = 0;
    auto j = f();    //j的值为42,;f保存了我们创建它时v1的拷贝,也就是42
}

 由于被捕获的变量的值是在lambda时创建拷贝,因此随后对其修改不回影响到lambda内对象的值。

引用捕获:

void fcn()
{
    size_t v1 = 42;    //局部变量
    //对象f2包含v1的引用
    auto f2 = [&v1] {return v1;};
    v1 = 0;
    auto j = f2();    //j的值为0,f2保存v1的引用
}

注意,由于不能对返回局部变量的引用。因此,采用引用方式捕获一个变量,就必须确保被引用的对象在lambda执行的时候是存在的lambda捕获的都是局部变量,这些变量在函数结束以后就不复存在了。。(当以引用的方式捕获一个变量是,必须保证在lambda执行时变量是存在的)。

隐私捕获:在捕获列表中写一个&或者=

&告诉编译器采用引用捕获方式

=告诉编译器采用值捕获方式。

混用隐私捕获和显示捕获时,隐私捕获必须放在前面,即捕获列表中的第一个元素必须是一个&或=。同时,显示捕获与隐私捕获的方式必须不同。即如果隐私捕获时引用的方式(使用了&),那么显示捕获命名变量名必须采用值捕获。如果隐私捕获采用了值方式,那么显示捕获命名变量必须采用引用方式。

捕获形式 说明
[] 不捕获任何外部变量
[变量名, …] 默认以值得形式捕获指定的多个外部变量(用逗号分隔),如果引用捕获,需要显示声明(使用&说明符)
[this] 以值的形式捕获this指针
[=] 以值的形式捕获所有外部变量
[&] 以引用形式捕获所有外部变量
[=, &x] 变量x以引用形式捕获,其余变量以传值形式捕获
[&, x] 变量x以值的形式捕获,其余变量以引用形式捕获

可变lambda

默认情况下,采用值捕获的变量,lambda是不会修改其值的。如果我们希望一个被捕获的变量的值,就必须在参数列表首加上mutable关键字。可变lambda能省略参数列表:

void fcn3()
{
    size_t v1 = 42;    //局部变量
    //f可以改变它所捕获的变量的值
    auto f = [v1] () mutable { return ++v1; };
    v1 = 0;
    auto j = f();    //j为43
}

当然,若捕获的是一个非const类型,也可以用引用来修改其值

void fcn4()
{
    size_t v1 = 42;    //局部变量
    //v1 是一个非const变量
    //可以通过f2中的引用来改变它
    auto f2 = [&v1] { return ++v1; };
    v1 = 0;
    auto j = f();    //j为1
}

指定lambda返回类型:

 如果lambda的函数体包含任何单一return语句之外的内容,且没有指定返回类型,则返回void。此时就可能出错。如:

[] (int i ) { if(i < 0) return -1; else return i; };

 编译器会推断其返回的是void,但是他返回的是int。这个时候,就必须要用到尾置类型的返回:

[] (int i ) -> int  { if(i < 0) return -1; else return i; };

猜你喜欢

转载自blog.csdn.net/ypshowm/article/details/89135667
今日推荐