值捕获修改的是副本,不影响外部变量:用[x]或[=]捕获时,lambda内部拿到的是变量的独立副本,后续读写仅作用于该副本,外部变量x保持原值不变。

值捕获修改的是副本,不影响外部变量
用 [x] 或 [=] 捕获时,Lambda 内部拿到的是变量的**独立副本**。后续在 Lambda 里对这个变量的任何读写,都只作用于这份副本。
常见错误现象:int x = 10; auto f = [x]() { x = 20; }; f(); std::cout 输出仍是 <code>10,不是 20 —— 因为没加 mutable,编译直接报错;即使加了 mutable,外部 x 也不变。
- 值捕获的变量默认是
const的,不加mutable就连内部修改都不允许 -
mutable只解禁“修改副本”的权限,不改变“副本”这一本质 - 如果变量是类类型,会调用其拷贝构造函数;基本类型则是位拷贝
引用捕获修改的是原始变量本身
用 [&x] 或 [&] 捕获时,Lambda 内部操作的就是外部变量的引用,等价于给它起了个别名。
使用场景:需要在回调中更新循环计数器、状态标记、或配合 std::async / std::thread 共享状态时常用。
- 必须确保 Lambda 执行时,被引用的变量**仍然存活**,否则就是悬垂引用(dangling reference)
- 多个线程同时通过引用捕获修改同一变量,需自行加锁,Lambda 不提供线程安全
-
[&]隐式引用捕获所有用到的变量,容易意外延长栈变量生命周期,引发未定义行为
混合捕获时,每份变量的归属要单独看
像 [=, &y] 这种写法,y 是引用,其他变量(比如 x、z)全是值捕获 —— 修改 y 影响外部,修改 x 不影响。
容易踩的坑:误以为 [=, &y] 中的 = 是“按值捕获全部”,其实它只覆盖“未显式指定”的变量;而 [&, x] 则是“按引用捕获全部,但 x 强制按值”。两者语法方向相反,不能颠倒顺序。
- 隐式捕获符号(
=或&)必须放在捕获列表最前面 - 显式写出的变量(如
&y或x)优先级更高,覆盖隐式规则 - 混合捕获常用于“大部分只读快照 + 少量需更新的状态”,比如日志计数器 + 配置参数
mutable 只对值捕获变量生效,且仅限内部副本
mutable 关键字不是“解除 const 限制”的通用开关,它只作用于**按值捕获的变量**,且只让这些变量在 Lambda 内部可写 —— 它不会让引用捕获的变量变得更“可写”(本来就能写),也不会让外部变量变得可写。
典型误用:int x = 5; auto f = [&x]() mutable { x = 10; }; 这里 mutable 是多余的,编译通过但无意义;而 auto f = [x]() { x = 10; } 编译失败,必须加 mutable 才能通过。
-
mutable实际上是把 Lambda 对应的仿函数类的operator()声明为非 const 成员函数 - 值捕获变量存储在该仿函数类的成员中,
mutable允许修改这些成员 - 引用捕获变量在仿函数类中存为引用类型成员,本来就不受 const 成员函数限制
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











