信息发布→ 登录 注册 退出

c++ Lambda表达式的捕获列表是什么 [=]和[&]的区别【深入理解】

发布时间:2025-12-27

点击量:
捕获列表决定Lambda表达式如何访问外部变量:【=】按值捕获使用到的局部变量副本,【&】按引用捕获原变量,混合捕获如[=, &y]更安全清晰,本质是编译为闭包类成员。

捕获列表是 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]),原因:

  • 语义清晰:明确知道哪个变量怎么捕获;
  • 规避风险:防止意外按引用捕获将要销毁的变量;
  • 性能可控:大对象适合引用捕获,小对象或需要隔离时选值捕获;
  • 例如:int a = 10; std::string s = "hello"; auto f = [=, &s]() { a++; s += "!"; }; —— a 是副本(修改无效),s 是引用(修改生效)。

捕获的本质:lambda 是一个闭包类型对象

编译器把 lambda 编译成一个匿名类,捕获的变量变成该类的成员:

  • [=] → 成员是 const T(或带 mutable 时为 T);
  • [&] → 成员是 T&
  • 捕获列表决定了这个“闭包类”的数据成员声明方式,也决定了调用时的行为边界。
标签:# 区别  # 作用域  # c++  # 体内  # 仍可  # 自然地  # 会为  # 定了  # 决定了  # 就会  # 是一个  # 的是  # 都以  # this  # 对象  # copy  # 闭包  # 指针  # Lambda  # mutable  # int  # 局部变量  # auto  # const  # 成员函数  # 成员变量  # String  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!