值捕获[=]仅拷贝lambda体实际使用的自动变量值,不捕获this、静态/全局变量;引用捕获[&]以引用方式捕获使用变量,有生命周期风险;混合捕获可覆盖默认方式,[=, &x]表示x引用捕获其余值捕获。
![c++中的lambda捕获列表[=]和[&]的区别?(值传递与引用传递的差异)](https://img.php.cn/upload/article/001/431/639/176907222928489.png)
捕获列表 [=] 是值捕获,但不等于“所有变量都拷贝”
使用 [=] 时,lambda 会以值方式捕获当前作用域中**被 lambda 体实际使用到的**自动变量(即 odr-used)。没被用到的变量不会被捕获,哪怕写了 [=]。它不会捕获 this(除非显式写 [=, this]),也不会捕获静态局部变量或全局变量(它们本就不需要捕获)。
注意:即使变量是引用类型(如 int& x = y;),[=] 捕获的仍是该引用所指向对象的**值副本**,不是原引用本身。
- 若捕获对象不可拷贝(如
std::unique_ptr),编译失败 - 若对象很大,可能带来不必要的拷贝开销
- 修改捕获后的变量,不影响原变量
捕获列表 [&] 是引用捕获,生命周期风险必须手动管理
[&] 以引用方式捕获所有被 lambda 体实际使用的自动变量。它同样不捕获未使用的变量,也不捕获 this 自动(需显式加 [&, this])。
关键问题是:如果 lambda 在定义它的作用域结束后仍被调用(比如返回后存储、异步执行),而它引用的变量已经销毁,行为就是未定义的——常见 crash 或读脏内存。
立即学习“C++免费学习笔记(深入)”;
- 捕获的是变量本身的引用,修改 lambda 内部的
x就等于修改原变量 - 对只读场景更轻量(无拷贝),但极易误用
- 不能捕获临时对象(如函数返回的右值),因为其生命周期通常短于 lambda
混合捕获 [=, &x] 和 [=, x] 的行为差异
C++ 允许混合捕获,但规则严格:一旦用了 [=] 或 [&],其余显式捕获必须与之“方向一致”,除非显式覆盖。例如:
int a = 1, b = 2;
auto f1 = [=, &a]() { a++; b++; }; // 合法:a 引用捕获,b 值捕获
auto f2 = [&a, b]() { a++; b++; }; // 合法:a 引用,b 值
auto f3 = [=, b]() { }; // 错误:重复指定 b 的捕获方式
特别注意:[=, &x] 中的 &x 是对默认值捕获的**覆盖**,不是追加;而 [&, x] 中的 x 是对默认引用捕获的覆盖(此时 x 是值捕获)。
-
[=, &x]:绝大多数变量值捕获,仅x引用捕获 -
[&, x]:绝大多数变量引用捕获,仅x值捕获 - 不能混用
[=, x](x已被=覆盖,再写是重复)
捕获 this 的隐含规则和陷阱
在类成员函数中,[=] 和 [&] 都**不会自动捕获 this 指针**。这意味着 lambda 无法访问 this->member,除非你显式写 [=, this] 或 [&, this]。
更隐蔽的问题是:即使你写了 [=],它也只捕获 this 指针的值(即对象地址),而不是对象本身;所以你可以安全调用成员函数(只要对象还活着),但不能假设对象数据没被析构。
- 在异步回调中,
[=, this]很常见,但务必确保对象生命周期长于 lambda 执行期 - 用
shared_from_this()配合std::shared_ptr是更安全的替代方案 -
[this](无 = 或 &)等价于[=, this],C++17 起允许










