You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lambda默认捕获是什么?关于*this隐式捕获规则的疑问

Lambda捕获常见问题解答

1. Lambda的默认捕获是什么?

Lambda的默认捕获有两种核心类型,对应不同的自动捕获策略:

  • 值捕获默认:=:当捕获列表开头写=,Lambda会自动按值捕获它体内用到的当前作用域非静态局部变量。简单说就是把这些变量的副本存到Lambda对象里,后续修改副本不会影响原变量。
  • 引用捕获默认:&:如果开头写&,Lambda会自动按引用捕获体内用到的非静态局部变量。这时候Lambda操作的是原变量的引用,修改会直接影响原变量。

如果不写任何默认捕获(比如[]),你必须显式列出所有要捕获的变量,不然在Lambda里使用未捕获的变量会直接编译报错。

2. 关于“捕获默认值与*this隐式捕获”的困惑

我来拆解这句话里的关键点,帮你理清逻辑:

什么是“任一捕获默认值”?

“任一捕获默认值”就是指Lambda捕获列表里使用了=或者&作为默认捕获规则——不管后面有没有加显式捕获的变量,比如[=]、[&]、[=, &foo]、[&, bar]这些都属于“存在捕获默认值”的情况。

为什么=默认捕获时,*this会被隐式按引用捕获?

这是C11到C17的特殊规则(C++17之后有补充):
当你在类的成员函数里定义Lambda,并且Lambda用了默认捕获(不管是=还是&),只要Lambda体内访问了类的成员(比如直接写x,本质是this->x),就会隐式捕获this指针。

这里容易混淆的点是:默认捕获=是值捕获局部变量,但this不是局部变量——它是成员函数里的隐含指针,所以捕获规则不一样:

  • 即使写的是[=],捕获的也是this指针的副本(值捕获指针),但这个指针依然指向原来的类对象。所以你在Lambda里修改成员变量时,是通过这个指针操作原对象,看起来就像是“按引用捕获了整个对象”。
  • 如果是[&]默认捕获,捕获的是this指针的引用,效果和值捕获指针类似,都是操作原对象。

举个代码例子直观感受:

#include <iostream>
using namespace std;

class MyClass {
public:
    int x = 10;
    void test() {
        // =默认捕获
        auto lambda = [=]() {
            cout << "Lambda内x的值:" << x << endl; // 等价于this->x,隐式捕获this
            x = 20; // 修改的是原对象的x
        };
        lambda();
        cout << "原对象x的值:" << x << endl; // 输出20
    }
};

int main() {
    MyClass obj;
    obj.test();
    return 0;
}

如果想真正按值捕获整个对象(而非捕获指针),C++17之后可以用[=, *this],这时候Lambda会复制整个对象的副本,修改副本的成员不会影响原对象:

auto lambda = [=, *this]() {
    x = 30; // 修改的是副本的x
};
lambda();
cout << "原对象x的值:" << x << endl; // 还是20,不受影响

总结一下:只要Lambda有默认捕获(=或&),且体内用到了类成员,就会自动捕获this;不管默认捕获是值还是引用,通过this访问的都是原对象(直到C++17的*this捕获出现)。

内容的提问来源于stack exchange,提问作者MistyD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:00:58