[=]捕获当前作用域中被实际使用的变量的副本,[&]捕获其引用;未在lambda体中出现的变量不会被捕获,混合捕获如[x, &y]合法,类成员函数中需显式写[this],mutable允许修改值捕获的副本。

lambda捕获列表中[=]和[&]到底传什么
它们不是简单地“值传”或“引传”整个作用域,而是对**当前作用域中被lambda实际使用到的变量**,分别按值或按引用方式捕获。没在lambda体里出现的变量,哪怕写了[=]也不会被捕获。
关键点:[=]捕获的是变量的**副本**(调用时的快照),[&]捕获的是变量的**真实地址**(后续修改会影响原变量)。
-
[=]下修改捕获变量:只改副本,不影响外部同名变量 -
[&]下修改捕获变量:直接改外部变量,可能引发悬空引用(比如捕获了局部变量,lambda逃逸出作用域后被调用) - 混合捕获如
[a, &b]是合法的:a按值,b按引用
什么时候必须显式写捕获列表,不能只用[=]或[&]
当需要混合策略,或捕获this、或避免隐式捕获带来的生命周期风险时,显式列表是唯一安全选择。
典型场景:
立即学习“C++免费学习笔记(深入)”;
- 想按值捕获
int x,但按引用捕获std::vector(避免拷贝大对象)→ 写& v [x, &v] - 在类成员函数中访问
this->member,且需确保lambda能随对象存活 → 必须写[this]([=]不自动捕获this) - 捕获局部数组首地址:
int arr[3] = {1,2,3}; auto f = [&arr]{ /* ... */ };—— 这里&arr捕获的是整个数组的引用,类型是int(&)[3],不是int*
值捕获后修改变量,外部变量真的一点不受影响吗
绝大多数情况是的,但有一个例外:mutable关键字允许修改值捕获的副本,且该修改在多次调用间保持(因为副本是lambda对象的成员)。
int x = 10;
auto f = [=]() mutable {
x++; // 合法:修改的是副本
std::cout << x << "\n"; // 第一次调用输出11,第二次输出12
};
f(); f();
注意:mutable只解除对**值捕获变量**的const限定;对[&]捕获的变量,本来就能改,加mutable无意义。
另一个易错点:如果值捕获的是指针(如int* p = &x;),[=]捕获的是指针值(地址)的副本,但通过该指针仍可修改原始对象 —— 这不是引用传递,是“指针值传递后解引用”。
捕获std::unique_ptr时为什么[=]会编译失败
因为std::unique_ptr的拷贝构造函数被删除了,而[=]要求所有被值捕获的变量都可拷贝。[&]可以,但极度危险:一旦原unique_ptr析构,lambda内持有的引用就悬空。
正确做法只有两个:
- 用
[ptr = std::move(ptr)]实现移动捕获(C++14起支持)→ lambda内获得独占所有权 - 改用
std::shared_ptr,再用[=]或[ptr]值捕获(拷贝的是控制块,安全)
std::unique_ptrp = std::make_unique (42); auto f = [p = std::move(p)]() { std::cout << *p << "\n"; // OK:p已在lambda内完成移动 }; // 原p在此处已为空
别忽略移动捕获后的原变量状态——它已被置为有效但未定义值(通常是nullptr),后续再用就是未定义行为。











