C++ lambda 表达式除了[&] [=] [] 还有哪些形式

在 C++ 中,lambda 表达式的捕获列表(capture list)不仅限于 [&][=][],还有其他形式可以更灵活地控制捕获行为。以下是 C++ lambda 表达式捕获列表的完整形式及其用法:


1. 空捕获列表 []

  • 表示 lambda 表达式不捕获任何外部变量。
  • 只能使用 lambda 表达式的参数和局部变量。
int x = 10;
auto lambda = []() { 
    // 不能使用 x,因为没有捕获
    return 42; 
};

2. 按引用捕获 [&]

  • 表示 lambda 表达式通过引用捕获所有外部变量。
  • 对捕获变量的修改会反映到外部作用域。
int x = 10;
auto lambda = [&]() { 
    x = 20;  // 修改外部变量 x
    return x; 
};
lambda();
std::cout << x;  // 输出: 20

3. 按值捕获 [=]

  • 表示 lambda 表达式通过值捕获所有外部变量。
  • 对捕获变量的修改不会反映到外部作用域。
int x = 10;
auto lambda = [=]() { 
    // x 是只读的,不能修改
    return x + 1; 
};
std::cout << lambda();  // 输出: 11
std::cout << x;  // 输出: 10(未被修改)

4. 显式捕获特定变量

  • 可以显式指定捕获的变量,并选择是按引用捕获还是按值捕获。
按引用捕获特定变量 [&x, &y]
int x = 10, y = 20;
auto lambda = [&x, &y]() { 
    x = 30;
    y = 40;
};
lambda();
std::cout << x << " " << y;  // 输出: 30 40
按值捕获特定变量 [x, y]
int x = 10, y = 20;
auto lambda = [x, y]() { 
    // x 和 y 是只读的
    return x + y; 
};
std::cout << lambda();  // 输出: 30

5. 混合捕获

  • 可以混合使用按引用捕获和按值捕获。
int x = 10, y = 20;
auto lambda = [&x, y]() { 
    x = 30;  // 修改 x(按引用捕获)
    // y 是只读的(按值捕获)
    return x + y; 
};
lambda();
std::cout << x << " " << y;  // 输出: 30 20

6. 隐式捕获与显式捕获结合

  • 可以使用 [&, x][=, &x] 的形式,表示默认捕获方式(&=),同时显式指定某些变量的捕获方式。
默认按引用捕获,显式按值捕获 [&, x]
int x = 10, y = 20;
auto lambda = [&, x]() { 
    y = 30;  // 修改 y(默认按引用捕获)
    // x 是只读的(显式按值捕获)
    return x + y; 
};
lambda();
std::cout << x << " " << y;  // 输出: 10 30
默认按值捕获,显式按引用捕获 [=, &x]
int x = 10, y = 20;
auto lambda = [=, &x]() { 
    x = 30;  // 修改 x(显式按引用捕获)
    // y 是只读的(默认按值捕获)
    return x + y; 
};
lambda();
std::cout << x << " " << y;  // 输出: 30 20

7. 捕获 this 指针

  • 在类的成员函数中,lambda 表达式可以捕获 this 指针,以访问类的成员变量和成员函数。
class MyClass {
public:
    int x = 10;
    void print() {
        auto lambda = [this]() { 
            std::cout << x;  // 访问成员变量 x
        };
        lambda();
    }
};

MyClass obj;
obj.print();  // 输出: 10

8. 捕获初始化(C++14 引入)

  • 在 C++14 中,可以在捕获列表中初始化变量。这种方式允许在 lambda 表达式中定义新的变量。
int x = 10;
auto lambda = [y = x + 1]() { 
    return y; 
};
std::cout << lambda();  // 输出: 11

9. 可变 lambda(mutable 关键字)

  • 默认情况下,按值捕获的变量是只读的。如果需要在 lambda 表达式中修改按值捕获的变量,可以使用 mutable 关键字。
int x = 10;
auto lambda = [x]() mutable { 
    x = 20;  // 修改按值捕获的变量
    return x; 
};
lambda();
std::cout << x;  // 输出: 10(外部变量未被修改)

总结

C++ lambda 表达式的捕获列表形式非常灵活,主要包括:

  1. 空捕获列表 []
  2. 按引用捕获 [&]
  3. 按值捕获 [=]
  4. 显式捕获特定变量 [x, &y]
  5. 混合捕获 [&, x][=, &x]
  6. 捕获 this 指针
  7. 捕获初始化(C++14)
  8. 可变 lambda(mutable

根据具体需求选择合适的捕获方式,可以更好地控制 lambda 表达式的行为。如果你有其他问题,欢迎继续讨论!

你可能感兴趣的:(C++,c++)