捕获列表决定Lambda表达式如何访问外部变量:【=】按值捕获使用到的局部变量副本,【&】按引用捕获原变量,混合捕获如[=, &y]更安全清晰,本质是编译为闭包类成员。
![c++ lambda表达式的捕获列表是什么 [=]和[&]的区别【深入理解】](https://img.php.cn/upload/article/001/431/639/176680732911980.png)
捕获列表是 C++ Lambda 表达式中用于指定如何访问外部作用域变量的关键语法部分,它决定了 lambda 函数体内部能否以及以何种方式(值拷贝 or 引用)使用定义位置附近的局部变量。
【=】:默认按值捕获(copy capture)
写成 [=] 表示:对当前作用域中所有**被 lambda 体实际使用到的自动变量(local variables)**,都以**值拷贝的方式**捕获。编译器会为每个被捕获的变量在 lambda 对象内部创建一份独立副本。
- 捕获后,lambda 内部修改的是副本,不影响原变量;
- 原变量即使生命周期结束(比如函数返回),lambda 仍可安全使用其副本;
- 不能通过
[=]修改外部变量本身(除非 lambda 声明为mutable,此时修改的也只是副本); - 注意:
[=]不捕获this指针(类成员函数内需显式写[=, this]或直接用[this])。
[&]:默认按引用捕获(reference capture)
写成 [&] 表示:对所有**被 lambda 体实际使用到的自动变量**,都以**引用方式**捕获。lambda 内部操作的就是原始变量本身。
- lambda 内对变量的读写,直接反映到原变量上;
- 危险点:若原变量在 lambda 被调用前已销毁(如函数返回后执行该 lambda),就会引发未定义行为(dangling reference);
- 可以自然地修改外部变量,无需
mutable; - 在类成员函数中,
[&]默认也捕获this(即隐含[&, this]),因此能访问和修改成员变量。
混合捕获与显式指定更安全
实际开发中,推荐避免纯 [=] 或纯 [&],而采用显式列表(如 [x, &y, z])或混合形式(如 [=, &y]、[&, x]),原因:
立即学习“C++免费学习笔记(深入)”;
- 语义清晰:明确知道哪个变量怎么捕获;
- 规避风险:防止意外按引用捕获将要销毁的变量;
- 性能可控:大对象适合引用捕获,小对象或需要隔离时选值捕获;
- 例如:
int a = 10; std::string s = "hello"; auto f = [=, &s]() { a++; s += "!"; };——a是副本(修改无效),s是引用(修改生效)。
捕获的本质:lambda 是一个闭包类型对象
编译器把 lambda 编译成一个匿名类,捕获的变量变成该类的成员:
-
[=]→ 成员是const T(或带mutable时为T); -
[&]→ 成员是T&; - 捕获列表决定了这个“闭包类”的数据成员声明方式,也决定了调用时的行为边界。









