Lambda表达式语法为capture->return_type{body},方括号不可省;捕获列表、参数列表、函数体缺一不可,箭头及返回类型在可推导时可省略。

lambda 表达式基本语法长什么样
写法就是 [capture](params) -> return_type { body },方括号、圆括号、花括号一个都不能少,箭头部分(-> return_type)可以省略——编译器能推导时就自动推了。
常见错误是漏掉方括号,比如写成 (int x) { return x * 2; },这根本不是合法 lambda,编译直接报 error: expected unqualified-id。
实操建议:
- 捕获列表
[x]是按值拷贝变量x;[&x]是按引用捕获;[=]按值捕获所有外部变量;[&]按引用捕获全部 - 参数列表为空时写
(),不能省;C++14 起支持auto参数,如[](auto x) { return x + 1; } - 返回类型不写时,若 body 只有一条
return语句,编译器会自动推导;否则默认为void
什么时候必须显式写返回类型
当 lambda 体里有多个分支、或有非 return 语句(比如 if 后跟普通表达式)、或者你想强制返回引用/const 类型时,编译器没法安全推导,就得手动加 ->。
立即学习“C++免费学习笔记(深入)”;
典型例子:想返回局部变量的引用?不行,但返回外部变量的引用可以——前提是捕获方式对得上。
示例:
int a = 42;
auto f = [&a]() -> int& { return a; }; // ✅ 捕获引用,返回引用
auto g = [a]() -> int& { return a; }; // ❌ 编译失败:返回局部拷贝的引用容易踩的坑:用 [=] 捕获后还试图返回某个变量的引用,实际返回的是副本的引用,行为未定义。
lambda 能不能存到普通函数指针里
不能,除非它不捕获任何变量(即空捕获列表 [])。因为带捕获的 lambda 本质是闭包类型,每个 lambda 表达式生成的类型都唯一,且不可赋值给函数指针。
常见误用场景:往只接受 void (*)() 的 C 风格 API 里传带捕获的 lambda,编译报错 cannot convert ... to ... in argument。
解决办法:
- 用
std::function包一层(运行时开销小,但非零) - 改用
[]捕获,把需要的数据通过参数传进去 - 实在要塞进函数指针,只能把捕获变量提成全局或静态,再用
[]访问——但通常不推荐
捕获 this 和成员变量要注意什么
在类成员函数里写 [this]() { ... } 是安全的,能访问 this->member;但 [=] 或 [&] 在 C++17 前不隐含捕获 this,C++17 起才规定 [=] 自动包含 this(如果用到了成员)。
真正危险的是:lambda 生命周期比对象长,而你又用了 [this] 或 [&] 捕获了成员变量。对象析构后调用 lambda,就是野指针。
实操建议:
- 优先考虑
[weak_ptr<t> wp = shared_from_this()]</t>捕获,调用前if (auto sp = wp.lock()) { ... } - 明确生命周期关系,比如只在本函数内使用 lambda,那就放心用
[this] - 避免在异步回调、线程池任务等脱离当前作用域的场景里无防护地捕获
this
最常被忽略的一点:lambda 的“捕获”不是深拷贝,也不是智能指针管理,它只是复制或引用原始变量——这个语义一旦和对象生命周期搅在一起,问题就藏得特别深。


















