C++ lambda捕获外部变量靠的是[]捕获列表,本质是编译器生成带成员变量的匿名类:值捕获存副本(不可修改除非mutable),引用捕获存地址(可改原变量但易悬垂),混合捕获需显式声明,隐式捕获[=]和[&]仅作用于实际使用的局部变量和参数。

直接说结论:C++ lambda 捕获外部变量靠的是 [] 捕获列表,它不是“传参”,而是让编译器生成一个带成员变量的匿名类——捕获方式决定了这些成员是值类型还是引用类型,也决定了你能不能改、改了影响谁。
值捕获:[x] 和 [=] 的行为差异
值捕获会拷贝变量到 lambda 对象内部,但要注意两点:一是拷贝发生在 lambda 创建时,不是调用时;二是默认情况下 operator() 是 const 的,所以捕获的副本不可修改。
-
[x]只捕获指定变量x(需在作用域内可见) -
[=]捕获当前作用域所有**局部变量和函数参数**(不包括全局/静态变量,也不包括类成员变量本身,但会隐式捕获this) - 如果想在 lambda 内修改值捕获的副本,必须加
mutable,例如:[x]() mutable { x = 100; } - 修改后只影响 lambda 内部副本,原变量完全不受影响
引用捕获:[&x] 和 [&] 的生存期风险
引用捕获存储的是变量地址,效率高但极容易出悬垂引用(dangling reference)——只要 lambda 在原始变量销毁后还被调用,行为未定义。
-
[&x]显式按引用捕获单个变量x -
[&]引用捕获当前作用域所有局部变量和函数参数(同样不捕获全局/静态变量) - 引用捕获不需要
mutable,lambda 内可直接修改原始变量 - 常见陷阱:把 lambda 存进容器或返回给调用方,而捕获的局部变量已在函数退出时析构
混合捕获:[=, &y] 或 [&, x] 的适用场景
混合捕获用来平衡安全与灵活性。比如你想读取大部分变量的快照,但又需要实时更新某个状态变量。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
-
[=, &y]:其余变量都值捕获,y单独引用捕获 -
[&, x]:其余变量都引用捕获,x单独值捕获(防止意外修改或延长生命周期) - 注意:同一个变量不能既按值又按引用捕获,否则编译报错
error: 'x' is captured twice - 混合捕获中,
this的处理仍遵循默认规则:[=, &y]会隐式值捕获this,[&, x]会隐式引用捕获this
捕获 this 和类成员变量的常见误解
在类成员函数里写 lambda,[=] 看似捕获了所有变量,其实它捕获的是 this 指针,不是成员变量本身。访问 member_var 实际等价于 this->member_var。
- 这意味着:如果 lambda 生命周期超过对象本身,调用时访问成员变量就是野指针
-
[this]显式写出来更清晰,也方便配合weak_ptr做生命周期管理 - 想真正按值捕获某个成员变量,得写成
[member_var = this->member_var](C++14 起支持初始化捕获) - 静态成员变量、全局变量无需捕获,lambda 内可直接访问
最常被忽略的点是:捕获行为在 lambda 构造时就固定了,和后续变量变化无关;而引用捕获的危险性往往在运行时才暴露,调试困难。写的时候多问一句:“这个 lambda 会在哪被调用?那时我捕获的东西还在吗?”

















