标签 匿名函数 下的文章

C++ | Lambda表达式


干啥的

C++ lambda表达式是一种匿名函数,它可以在需要函数对象的地方使用,而不需要显式地定义一个函数。

语法

[capture] (params) opt -> ret { body; }
[捕获列表](参数)mutable(可选)异常属性(可选)->返回类型{函数体}

示例

std::function<int(double)> func = [](double x)->int{ return round(x); }
std::cout << func(1.3) << endl;

捕获列表

lambda表达式的捕获列表用于指定在lambda函数体中可以访问的外部变量。捕获列表可以为空,也可以包含一个或多个捕获项,每个捕获项可以是变量、引用或者this指针。

捕获列表有以下几种形式:

  • 值捕获(value capture):通过值捕获,lambda表达式会在创建时拷贝外部变量的值,并在函数体中使用该拷贝。捕获列表使用方括号[]表示,后面跟着要捕获的变量名。例如:[x, y]表示值捕获变量x和y。
  • 引用捕获(reference capture):通过引用捕获,lambda表达式会在创建时绑定到外部变量的引用,并在函数体中使用该引用。捕获列表使用方括号[]表示,后面跟着要捕获的变量名前加上&符号。例如:[&x, &y]表示引用捕获变量x和y。
  • 隐式捕获(implicit capture):通过隐式捕获,lambda表达式会根据使用的外部变量自动推断捕获方式。捕获列表使用方括号[]表示,但不指定具体的变量名。例如:[=]表示值捕获所有外部变量,[&]表示引用捕获所有外部变量。
  • this指针捕获:通过this指针捕获,lambda表达式可以访问当前对象的成员变量。捕获列表使用方括号[]表示,后面跟着this关键字。例如:[this]表示通过值捕获当前对象的指针。

捕获列表中的变量可以在lambda函数体中使用,但不能修改(除非使用mutable关键字)。捕获列表的选择取决于外部变量的生命周期和使用方式,需要根据具体情况进行选择。

代码示例

#include <iostream>

class Example {
public:
    Example(int x) : x(x) {}

    void lambdaExample() {
        int y = 10;
        int z = 20;

        // 值捕获x,引用捕获y,隐式捕获z
        auto lambda = [&y, z, this]() mutable {
            std::cout << "x: " << x << std::endl;
            std::cout << "y: " << y << std::endl;
            std::cout << "z: " << z << std::endl;
            std::cout << "a: " << a << std::endl;

            x++; // 值捕获的变量可以修改,需要使用mutable关键字
            y++;
            // z++; // 隐式捕获的变量不能修改
            a++;
        };

        lambda();

        std::cout << "x after lambda: " << x << std::endl;
        std::cout << "y after lambda: " << y << std::endl;
        std::cout << "z after lambda: " << z << std::endl;
        std::cout << "a after lambda: " << a << std::endl;
    }

private:
    int x;
    int a = 100;
};

int main() {
    Example example(5);
    example.lambdaExample();

    return 0;
}

/**
x: 5
y: 10
z: 20
a: 100
x after lambda: 6
y after lambda: 11
z after lambda: 20
a after lambda: 101
**/

在上述示例中,lambda表达式中的捕获列表包含了部分捕获形式。值捕获了外部变量x,引用捕获了外部变量y,this指针捕获了成员变量a和变量x。lambda函数体中打印了捕获的变量,并对值捕获的变量进行了修改(需要使用mutable关键字)。在lambda函数执行后,可以看到外部变量z的值没有改变,而成员变量x,y,a的值增加了。