按值捕获[x]复制变量,修改仅作用于副本,不影响原变量;内置类型直接赋值,类对象调用拷贝构造函数;如需修改副本须加mutable关键字。

按值捕获([x])会复制变量,修改不影响原变量
按值捕获在 lambda 创建时对捕获的变量做一次拷贝,后续 lambda 内部对它的任何修改都只作用于副本。适用于不需要同步更新、或原变量生命周期可能早于 lambda 的场景。
常见错误:误以为修改 [x] 中的 x 能改变外部变量,实际完全无关。
-
[x]捕获的是x当前值的副本(调用x的拷贝构造函数) - 如果
x是内置类型(如int),就是简单赋值;如果是类对象,会调用拷贝构造函数 - lambda 体中对
x赋值(如x = 42;)不会影响外部同名变量 - 若需在 lambda 内修改捕获的副本,必须显式加
mutable关键字,否则编译报错:error: assignment of read-only variable 'x'
int x = 10;
auto f = [x]() mutable {
x = 99; // ✅ 允许:修改副本
std::cout << x << "\n"; // 输出 99
};
f();
std::cout << x << "\n"; // 输出 10:原变量未变
按引用捕获([&x])共享变量,修改直接影响原变量
按引用捕获不复制,而是保存对原变量的引用。lambda 内部对 x 的读写等价于直接操作外部变量。适用于需要实时反映变量变化,或避免拷贝开销的场景。
致命风险:若外部变量在 lambda 调用前已销毁(如局部变量出作用域),再调用 lambda 会导致未定义行为(常见 crash 或随机值)。
立即学习“C++免费学习笔记(深入)”;
-
[&x]捕获的是x的引用,不触发拷贝或移动 - lambda 内修改
x就是修改原始变量,无需mutable - 若捕获了局部变量的引用,而 lambda 在该局部变量生命周期结束后被调用,程序崩溃概率极高
- 调试时常见错误信息:
use of deleted value、segmentation fault或输出垃圾值
int x = 10;
auto f = [&x]() {
x = 88; // ✅ 直接改原变量
std::cout << x << "\n"; // 输出 88
};
f();
std::cout << x << "\n"; // 输出 88
混合捕获与默认捕获([=, &y] 或 [&, x])要格外小心
混合捕获允许同时使用默认按值(=)和个别按引用(&y),或默认按引用(&)加个别按值(x)。但容易混淆哪些是引用、哪些是值,尤其当变量名相似或嵌套作用域存在同名变量时。
典型陷阱:默认按值捕获后,又用 &y 显式按引用捕获一个本可按值处理的变量,结果无意中引入悬垂引用。
-
[=, &y]:除y外所有变量按值捕获;y按引用——注意y必须在 lambda 存活期间有效 -
[&, x]:除x外所有变量按引用捕获;x按值——此时若x是局部变量,按值捕获安全;但其他变量全靠引用,风险集中 - 不能同时写
[=, x]或[&, &y],编译器会报错:error: duplicate 'x' in capture list - VS 和 Clang 对混合捕获的诊断较弱,运行时出问题才暴露
捕获 this 时,[this] 和 [*this] 的本质区别
在类成员函数中,[this] 捕获的是当前对象指针的副本,lambda 内可通过 this-> 访问成员(包括非 const 成员函数);而 [*this](C++17 起支持)捕获的是当前对象的完整副本(按值),lambda 内访问的是副本的成员,与原对象彻底隔离。
这个区别常被忽略,尤其在异步回调中:用 [this] 可能导致访问已析构对象;用 [*this] 则无此风险,但无法修改原对象状态,且拷贝开销大。
-
[this]:捕获指针,轻量,但要求对象生命周期 ≥ lambda 生命周期 -
[*this]:捕获整个对象(调用拷贝构造函数),lambda 内所有成员访问都作用于副本 - 若类含指针成员或资源句柄,
[*this]还需确保类正确实现深拷贝,否则仍可能出问题 - 现代惯用法倾向:优先用
[weak_ptr配合w = shared_from_this()] lock()安全访问,而非裸[this]
struct Widget {
int data = 42;
void go() {
auto bad = [this]() { data = 999; }; // 修改原对象
auto good = [*this]() mutable { data = 777; }; // 修改副本,原 data 不变
}
};
捕获列表不是语法糖,它直接决定内存布局、生命周期依赖和线程安全性。最易被忽略的是:按引用捕获的变量是否真的“活得到时候”,以及 mutable 仅解除副本的只读性,对引用捕获无效。










