自动参数捕获的扣除规则是什么?

What are the deduction rules for automatic argument capture?

本文关键字:规则 是什么 参数      更新时间:2023-10-16

我之前看到了这段代码的等效物,我有点惊讶地发现它按预期工作:

#include <iostream>
int main() 
{
int a = 10;
[=]() mutable {
[&]() {
a += 10;
std::cout << "nested lambda: a=" << a << std::endl;
}(); // call nested lambda
}(); // call first lambda
std::cout << "a=" << a << std::endl;
}

如愿以偿,输出为

nested lambda: a=20
a=10

令我惊讶的是,编译器发现a在嵌套的 lambda 中使用,并按第一个 lambda 中的值正确捕获它,即使它没有在那里显式使用。 即,编译器必须在嵌套 lambda 中的a与外部作用域中的a之间建立连接。我认为参数捕获需要明确(即[a]在第一个 lambda 中,[&a]在嵌套中(,以便它工作。

自动参数捕获的扣除规则是什么?

这在 [expr.prim.lambda.capture]p7 中有描述:

出于 lambda 捕获的目的,表达式可能引用本地实体,如下所示:

  • 命名本地实体的 id 表达式可能引用该实体;命名一个或多个非静态类成员且不形成指向成员的指针的id 表达式([expr.unary.op]( 可能引用*this

  • this表达式可能引用*this

  • lambda 表达式可能引用由其简单捕获命名的本地实体。

如果表达式可能引用了该表达式在其中可用的声明性区域中的局部实体,并且如果忽略了任何封闭typeid表达式 ([expr.typeid]( 的效果,则表示该实体被每个干预的lambda 表达式隐式捕获,并具有未显式捕获它的关联捕获默认值

换句话说:

如果用法需要定义,则 lambda 会在以下情况下隐式捕获,typeid表达式将被忽略,并且不会显式捕获它们:

变量
  • 被命名;或者如果出现非静态类成员的名称(不计算指向成员的指针(,则隐式捕获*this,或者

  • this出现,则隐式捕获*this

隐式捕获的实体由每个具有默认捕获的干预 lambda 隐式捕获。