按值捕获[x]生成独立副本,但默认const;加mutable才可修改副本,不影响原变量,且拷贝构造函数副作用真实发生。
[x])实际是拷贝,不是“只读副本”很多人误以为 [x] 捕获后 x 就彻底与原变量无关、且不可修改——其实前半对,后半错。按值捕获确实会调用 x 的拷贝构造函数(或移动构造,若满足条件),生成闭包内部的独立副本;但这个副本默认是 const 的,除非 lambda 声明为 mutable。
mutable 时,即使捕获的是非 const 变量,也无法在 lambda 体内修改该副本(编译报错:assignment of read-only variable)mutable 后,可修改副本,但不影响外部原始变量int a = 42;
auto f = [a]() mutable { a = 99; }; // OK:修改的是副本
f();
std::cout << a << "\n"; // 输出 42,原变量未变
[&x])绑定的是运行时对象,不是声明时快照引用捕获不拷贝,只存一个引用,因此闭包内对 x 的读写直接作用于原始变量。但它不保证该变量在 lambda 被调用时仍有效——这是悬垂引用(dangling reference)的高发场景。
auto f = [&s]{ return s.size(); }; 中若 s 是函数局部 std::string,lambda 返回后调用必崩溃[&] 全局引用捕获更隐蔽:它会把所有自动变量都按引用抓进来,容易无意中延长生命周期依赖C++ 不允许隐式混用;必须明确写出每个捕获项。常见错误是想“大部分按引用、个别按值”,却误写成 [&, x] 或 [=, &y]——后者在 C++11/14 中非法,C++17 才支持 [=, &y],但 [&, x] 始终合法(先全部引用,再显式覆盖 x 为值捕获)。
[&, x]:除 x 外所有变量按引用捕获,x 按值捕获[=, &y]:C++17 起才允许,表示除 y 外所有变量按值捕获,y 按引用捕获x 和 &x,编译器报错:duplicate capture of 'x'
没有垃圾回收的 C++ 里,闭包本身不管理捕获对象的生存期。按值捕获靠拷贝“脱钩”,相对安全;引用捕获则完全依赖程序员手动确保“lambda 死亡前,被引对象不能死”。这在回调、线程、信号槽等场景极易翻车。
std::thread 拆包 lambda?别直接传 [&x],改用 [x] 或 std
::ref(x) 显式控制std::shared_ptr 包裹共享数据,再按值捕获指针,比裸引用更可控真正难的不是语法,而是判断“这里该用哪种捕获”——得看变量谁拥有、谁销毁、lambda 谁调用、何时调用。写完 lambda,先盯三秒捕获列表,问自己:这个变量,三年后还在不在?