值捕获复制变量且默认只读,需mutable才可修改副本;引用捕获共享原始变量但易致悬空;混合捕获与初始化捕获可精准控制生命周期;捕获this需防对象提前销毁。

值捕获会复制变量,但默认不可修改
值捕获 [x] 或隐式 [=] 会让 Lambda 在构造时拷贝一份外部变量的当前值,存为自身闭包对象的成员。这意味着后续外部变量变化不影响 Lambda 内部使用的值。
但注意:默认情况下,值捕获的变量在 Lambda 体内是 const 的——哪怕你没写 mutable,编译器也会隐式加 const 限定。
-
[x]() { x = 10; }→ 编译错误:assignment of read-only variable ‘x’ -
[x]() mutable { x = 10; }→ 合法,但只改了副本,外部x不变 - 对大型对象(如
std::vector、std::string)值捕获可能触发深拷贝,嵌入式或高频调用场景需警惕开销
引用捕获共享内存,生命周期必须可控
引用捕获 [&x] 或 [&] 存储的是变量地址,Lambda 内部读写直接作用于原始变量。这很高效,但极其危险:一旦外部变量提前销毁,Lambda 再次调用就会访问悬空引用。
- 局部变量被引用捕获后,Lambda 若逃逸出作用域(比如存入
std::function、传给异步任务),就大概率崩溃 -
std::thread t([&x]{ ++x; }); t.detach();→ 若x在线程执行前已析构,UB(未定义行为) - 类成员函数中用
[&]捕获,等价于捕获this和所有局部变量,但若 Lambda 被长期持有,this可能失效
混合捕获和初始化捕获是安全折中方案
纯 [=] 或 [&] 容易失控;显式列出变量又繁琐。混合捕获(如 [=, &y])和 C++14 初始化捕获(如 [ptr = new int(42)])能更精准控制所有权和生命周期。
-
[=, &callback]:其他变量按值,唯独回调函数按引用——避免拷贝函数对象,又不担心其生命周期(通常由调用方保证) -
[handle = std::move(local_handle)]:把移动语义带进捕获,避免冗余拷贝,且明确转移资源所有权 -
[id = get_id(), &log]:用表达式预计算值,再按值捕获;同时引用日志对象供调试输出
捕获 this 要特别小心隐式绑定
在类成员函数中,[this] 显式捕获当前对象指针,[=] 和 [&] 也会隐式包含 this。这意味着 Lambda 访问 member_var 实际是通过 this->member_var,而非拷贝成员。
- 若 Lambda 被存储到对象外(如全局队列、线程池),而原对象已被销毁,
this就成悬空指针 -
[this]() { member_func(); }和[=]() { member_func(); }行为一致,都依赖this有效性 - 真正安全的做法是:需要长期持有时,改用
std::shared_ptr捕获,或确保 Lambda 生命周期不超过对象生命周期
实际项目里最容易被忽略的不是语法怎么写,而是「谁负责变量的生存期」——值捕获推卸了责任,引用捕获却把责任悄悄转嫁给了调用方。写完一个 Lambda,务必问一句:它会在哪儿被调用?那时被捕获的东西还在不在?
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











