【一】Lambda表达式

1.Lambda表达式概述
​ Lambda表达式是现代C++在C ++ 11和更高版本中的一个新的语法糖 ,在C++11、C++14、C++17和C++20中Lambda表达的内容还在不断更新。 lambda表达式(也称为lambda函数)是在调用或作为函数参数传递的位置处定义匿名函数对象的便捷方法。通常,lambda用于封装传递给算法或异步方法的几行代码 。
2.Lambda表达式定义

2.1 Lambda表达式语法定义


1) 捕获列表。在C ++规范中也称为Lambda导入器, 捕获列表总是出现在Lambda函数的开始处。实际上,[]是Lambda引出符。编译器根据该引出符判断接下来的代码是否是Lambda函数,捕获列表能够捕捉上下文中的变量以供Lambda函数使用。

  • []表示不捕获任何变量
  • [var]表示值传递方式捕获变量var
  • [=]表示值传递方式捕获所有父作用域的变量(包括this)
  • [&var]表示引用传递捕捉变量var
  • [&]表示引用传递方式捕捉所有父作用域的变量(包括this)
  • [this]表示值传递方式捕捉当前的this指针
  • [=,&a,&b]表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量
  • [&,a,this]表示以值传递的方式捕捉变量a和this,引用传递方式捕捉其它所有变量。

2) 参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略。
3) 可变规格*。mutable修饰符, 默认情况下Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。*
4)异常说明。用于Lamdba表达式内部函数抛出异常。
5)返回类型。 追踪返回类型形式声明函数的返回类型。我们可以在不需要返回值的时候也可以连同符号”->”一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。
6)lambda函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
 

3.  应用案例

#include <iostream>
using namespace std;
class Test
{
public:
    void Func(int x, int y)
    {
        auto f = [this] {
            return m_a;
        };
        cout << f() << endl;
    }

private:
    int m_a = 10;
};
int main(int argc, const char* argv[])
{
    //1.[]不捕获任何变量
    int j = 5;
//    auto f = [] {return j; };	//编译报错

    //2. 静态局部变量,可以直接使用
    static int i = 9;
    auto f1 = [] {return i; };
    cout << f1() << endl;	//15

    //3. [&]捕获外部作用域中所有变量,并作为引用在函数体内使用
    int m = 9;
    auto f2 = [&] {
        m = 15;
        return m;
    };
    cout << f2() << endl;	//15
    cout << m << endl;	//15

    //4. [=]捕获外部作用域中所有变量,并作为值(副本)在函数体内使用,但不许给它赋值
    int k = 1;
    auto f3 = [=] {
//        k = 15;	//非法,不可以给它赋值,因为是以值的方式捕获
    };

    //5. [this]捕获当前类中this指针,让lambda表达式有和当前类成员函数同样的访问权限。
    //如果[]中已经使用了 & 或 =,那么默认已经使用了this,可以使用当前类的成员变量和成员函数。
    Test test;
    test.Func(10, 12);

    //6. [变量名]如果多个变量名,则彼此之间用,分割,按值捕获变量名代表的变量,其他的变量则不捕获
    //	[&变量名]按引用捕获变量名代表的变量,同时不捕获其他变量
    int a = 10, b = 5;
    auto f4 = [a, b] {	//[&a, &b]
        cout << a <<" " <<  b << endl;
    };
    f4();

    //7. [=,&变量名] 按值捕获所有外部变量,但按引用捕获&中所指的变量,
    //=必须在开头位置,表示默认以值捕获(隐式捕获方式),后续其他的都是显示捕获
    auto f5 = [=, &a, &b] {
        cout << k << " " << a << " " << b << endl;
    };

    //8. [&, 变量名] 和7相反作用
    auto f6 = [&, a, b] {
        cout << k << " " << a << " " << b << endl;
    };

    return 0;
}