C++11 新特性:Lambda 捕获列表

Lambda 表达式的捕获列表定义了从定义 Lambda 的封闭作用域捕获哪些变量,以及如何捕获这些变量(通过值或引用)。

捕获列表使得 Lambda 表达式能够访问并操作定义它的作用域之外的变量。

下面是捕获列表的各种用法的详细描述:

1. 值捕获(Copy Capture)

通过值捕获的方式,Lambda表达式会复制捕获列表中指定的变量的当前值,并在Lambda表达式内部使用这个复制的值。这意味着Lambda表达式内部对这些变量的修改不会影响原始变量。

#include <iostream>

int main() {
    int x = 10;
    auto lambda = [x]() mutable {
        x *= 2; // 修改的是复制的值,不影响原始变量x
        std::cout << "Inside lambda: " << x << std::endl;
    };
    lambda();
    std::cout << "Outside lambda: " << x << std::endl; // 输出10,x的值未改变
}

输出:

Inside lambda: 20
Outside lambda: 10

注意mutable关键字的使用,如果没有该关键字,这段代码编译会出错。

main.cpp: In lambda function:
main.cpp:6:11: error: assignment of read-only variable ‘x’
    6 |         x *= 2; // 修改的是复制的值,不影响原始变量x
      |         ~~^~~~

在上篇文章中我也提到,默认情况下,通过值捕获的变量在Lambda内部是const的。如果 Lambda 需要修改它通过值捕获的变量,可以添加mutable关键字。

2. 引用捕获(Reference Capture)

通过引用捕获的方式,Lambda表达式会捕获指向原始变量的引用。这意味着Lambda表达式内部对这些变量的任何修改都会影响到原始变量。

#include <iostream>

int main() {
    int x = 10;
    auto lambda = [&x] {
        x *= 2; // 修改原始变量x的值
        std::cout << "Inside lambda: " << x << std::endl;
    };
    lambda();
    std::cout << "Outside lambda: " << x << std::endl; // 输出20,x的值被改变
}

输出:

Inside lambda: 20
Outside lambda: 20

3. 隐式捕获(Implicit Capture)

Lambda 表达式还支持隐式捕获模式,即自动捕获所需的外部变量,而无需显式列出它们。这可以通过[=](捕获所有外部变量通过值)或[&](捕获所有外部变量通过引用)来实现。

  • [=]:通过值捕获所有外部变量。
  • [&]:通过引用捕获所有外部变量。
#include <iostream>

int main() {
    int x = 10, y = 20;
    auto lambda_1 = [=] { std::cout << x + y << std::endl; }; // 隐式通过值捕获x和y
    lambda_1(); // 输出30
    auto lambda_2 = [&] { x =  x * 2; y = y * 2; };
    lambda_2();
    std::cout << "new value, x = " << x << ", y = " << y << std::endl;
}

输出:

30
new value, x = 20, y = 40

4. 混合捕获(Mixed Capture)

Lambda 表达式的捕获列表还可以混合使用值捕获和引用捕获,甚至包括隐式捕获和显式捕获的组合。

#include <iostream>

int main() {
    int x = 10, y = 20;
    auto lambda = [&, x] { // 通过引用捕获所有变量,但x通过值捕获
        std::cout << "Inside lambda, x: " << x << ", y: " << ++y << std::endl;
    };
    lambda(); // 输出 x: 10, y: 21
    std::cout << "Outside lambda, x: " << x << ", y: " << ++y << std::endl;
}

输出:

Inside lambda, x: 10, y: 21
Outside lambda, x: 10, y: 22

5. 捕获this指针

通过捕获this指针,Lambda 表达式可以访问类成员变量和成员函数。

#include <iostream>

struct S {
    int member = 42;
    void f() {
        auto lambda = [this] { std::cout << "Member: " << member << std::endl; };
        lambda();
    }
};

int main() {
    S().f(); // 输出 Member: 42
}

输出:

Member: 42

捕获列表是 Lambda 表达式的强大特性之一,有点绕,在后续的版本中,捕获列表又做了一些调整,综合起来更让人迷糊。但是正确使用捕获列表,Lambda 表达式的这种灵活性又可以帮助编写清晰、高效的现代 C++ 代码。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值