C++ lambda表达式必须符合“捕获列表->返回类型{函数体}”结构,捕获列表不可省略,返回类型可推导但多语句或类型不一致时需显式声明;五种捕获方式影响变量修改权、生命周期和悬垂引用;类内需显式捕获this访问成员;mutable允许修改值捕获副本;C++14支持初始化捕获实现移动语义。

lambda表达式基本写法:从语法结构开始
C++ lambda 不是“写出来就能用”,必须符合 capture -> return_type { body } 这个骨架。省略部分有严格规则:返回类型可推导时能省略 -> return_type,但一旦函数体含多条语句或含 return 表达式类型不一致,编译器就可能推导失败,报错如 error: no viable conversion from 'lambda' to 'std::function<...>'。
- 捕获列表
[...]必须存在(哪怕为空[]),不能省略 - 参数列表
(...)为空时可写成()或直接省略(仅当无参且无返回类型声明时) - 若 lambda 需被赋给
std::function或作为参数传入模板函数,建议显式写->返回类型,避免因推导差异导致模板实例化失败
捕获列表的五种写法及实际影响
捕获方式决定 lambda 能否修改变量、能否跨作用域存活、以及是否引发悬垂引用——不是语法糖,是内存模型问题。
-
[x]:值捕获,复制一份x。若x是大对象,注意拷贝开销;捕获后无法通过 lambda 修改外部x -
[&x]:引用捕获,不复制,但要求x的生命周期必须长于 lambda 本身,否则调用时触发未定义行为 -
[=]:默认值捕获,自动把当前作用域所有自动变量以值方式捕获。注意:不会捕获this(类成员函数中需显式写[this]或[=, this]) -
[&]:默认引用捕获,危险操作。一旦 lambda 在原作用域结束后被调用(比如存入容器、异步执行),几乎必然崩溃 -
[x, &y]:混合捕获,允许对不同变量用不同方式。但 C++17 起禁止[x, x]或[&x, x]这类重复/冲突写法,编译直接报错
在类成员函数里用 lambda 访问 this 和成员变量
类内写 lambda 时,this 不会自动捕获,更不会自动解引用。常见错误是以为 [=] 就能用 member_var,其实它只捕获局部变量,不包含隐式 this。
- 想访问非静态成员,必须显式捕获
this:[this]() { return member_var; } - 若只需读取 const 成员,可用
[*this](C++17)做值捕获,此时 lambda 拥有当前对象的一份副本,后续即使原对象析构也不影响它 - 捕获
this后,仍要通过this->或直接写成员名访问(编译器允许省略this->,但逻辑上仍是通过指针访问)
移动捕获与 mutable:让 lambda 修改捕获的值
默认情况下,lambda 的函数调用运算符是 const 成员函数,所以即使值捕获了变量,也不能在 body 中给它赋值。
立即学习“C++免费学习笔记(深入)”;
- 加
mutable关键字:使 operator() 非 const,允许修改值捕获的副本[x]() mutable { x = 42; } // 合法,x 是副本,改了不影响外部 - C++14 起支持初始化捕获(广义捕获):可移动大对象进去,避免无谓拷贝
[p = std::move(ptr)]() { /* 使用 p */ }注意:这里p是新变量,类型由std::move(ptr)推导,不是引用也不是指针别名
捕获列表看着简单,但每个符号都绑定着对象生命周期、所有权和调用时机——写完别急着跑,先盯住 [...] 里每个项,问一句:它现在在哪?之后还在不在?谁负责析构?










