值捕获[=]复制变量,修改副本不影响外部原始值;基本类型安全但不可反向写回,大对象可能深拷贝;需修改副本须加mutable关键字。

lambda 值捕获([=])会复制变量,修改不影响外部
值捕获是默认行为之一,用 [=] 表示把当前作用域中所有自动变量以值方式拷贝进 lambda 闭包。这意味着:闭包内部对这些变量的修改,不会反映到外部原始变量上。
常见错误是误以为 [=] 能同步更新外部状态,比如在循环中捕获循环变量后异步修改——实际改的是副本。
- 基本类型(
int、double)复制开销小,安全但不可反向写回 - 大对象(如
std::vector)会被完整拷贝,可能触发深拷贝构造,注意性能 - 若需捕获部分变量而非全部,用显式列表:
[x, y]或[=, &z](混合捕获)
int a = 10;
auto f = [=]() { a = 20; }; // 编译失败:a 是 const 副本(C++11 默认)
auto g = [=]() mutable { a = 20; }; // OK:mutable 允许修改副本
g();
std::cout << a << "\n"; // 输出 10,外部 a 未变
lambda 引用捕获([&])共享变量,但生命周期必须足够长
引用捕获用 [&],让 lambda 内部直接持有外部变量的引用。好处是能读写原始变量,坏处是极易引发悬垂引用(dangling reference)——尤其当 lambda 被返回或用于异步场景时。
典型崩溃场景:函数返回一个捕获局部变量引用的 lambda,调用方在函数返回后执行它。
立即学习“C++免费学习笔记(深入)”;
- 引用捕获不延长所捕获变量的生命周期,仅建立别名
- 禁止捕获即将销毁的局部变量(如函数栈上临时对象)
- 推荐只在 lambda 生命周期明确短于所捕获变量时使用,例如同一函数内立即调用
auto make_bad_lambda() {
int x = 42;
return [&x]() { return x; }; // 危险!x 在函数返回后销毁
}
// auto f = make_bad_lambda(); f(); // 未定义行为
混合捕获要显式声明,[=, &y] 比 [&, x] 更安全
C++ 允许混合值捕获与引用捕获,但语法有约束:不能同时用 [=] 和 [&],必须显式列出部分变量,并用 = 或 & 标明每个捕获方式。更安全的习惯是「默认值捕获 + 显式引用」,即 [=, &y]。
为什么?因为 [&, x] 表示“默认引用捕获 + 显式值捕获 x”,一旦遗漏某个需要引用的变量,它会被隐式按引用捕获,容易因生命周期问题出错;而 [=, &y] 中所有变量默认值捕获(安全),只对明确需要共享的 y 开放引用,意图清晰、风险可控。
-
[=, &y]:y 是引用,其余变量是副本 -
[&, x]:x 是副本,其余变量是引用(包括可能未声明的 this、参数等) - 捕获
this时,[this]是值捕获指针,[&]也会捕获this为引用,但不等于捕获成员变量本身
int a = 1, b = 2;
auto f = [=, &b]() {
a = 10; // 修改副本,无效
b = 20; // 修改原始 b,生效
};
f();
std::cout << a << ", " << b << "\n"; // 输出 "1, 20"
lambda 捕获 this 的两种方式区别很大
在类成员函数中,[this] 和 [=] 都会捕获 this 指针,但语义不同:[this] 明确表示只捕获当前对象指针,不自动捕获任何成员变量;而 [=] 会尝试按值捕获所有自动变量,包括 this(即复制指针),但**不会复制成员变量**——成员仍需通过 this->member 访问,本质还是间接引用。
真正危险的是误以为 [=] 把整个对象拷贝进了 lambda。它没有。如果你在 lambda 中保存了 [=] lambda 并在对象析构后调用,访问成员仍会 crash。
-
[this]:显式、轻量,适合只读/调用成员函数 -
[=]:隐式包含this,但易造成“以为值捕获了对象”的误解 - 若真需要复制整个对象,应手动捕获成员变量,如
[x = x_, y = y_](C++14 起支持初始化捕获)
struct S {
int val = 100;
auto get_lambda() {
return [this]() { return val; }; // OK,this 有效期间安全
// return [=]() { return val; }; // 同样依赖 this 存活,不是值拷贝 val
}
};
捕获的本质不是“变量内容”,而是“绑定方式”——值捕获是快照,引用捕获是链接,this 捕获只是指针。最常被忽略的,是以为 [=] 能隔离状态,其实它连成员变量都不复制。










