自动参数捕获的演绎规则是什么?

pin*_*gul 10 c++ lambda c++11 argument-deduction

我之前看到了相当于这段代码的东西,我有点惊讶地发现它按预期工作:

#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;
}
Run Code Online (Sandbox Code Playgroud)

如期望的那样,输出是

nested lambda: a=20
a=10
Run Code Online (Sandbox Code Playgroud)

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

自动参数捕获的演绎规则是什么?

Rak*_*111 9

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

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

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

  • this表达潜在的引用*this.

  • 一个拉姆达表达式可能引用由它的简单,捕获命名的本地实体.

如果表达式可能引用声明区域内的本地实体,并且该表达式可以使用,并且如果typeid忽略任何封闭表达式([expr.typeid])的效果,则可能会评估该表达式,该实体被称为每个插入的lambda表达式都隐式捕获了一个没有明确捕获它的相关捕获默认值.

换一种说法:

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

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

  • this出现,然后*this被隐含地捕获

每个插入的lambda使用默认捕获隐式捕获隐式捕获的实体.