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

10

我之前看到过这段代码的等效版本,但我有点惊讶它能按预期工作:

#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

我很惊讶编译器能够推断出嵌套lambda表达式中使用了a,并且即使第一个lambda表达式中没有显式地使用它,也可以正确地按值捕获它。也就是说,编译器必须将嵌套lambda表达式中的a与外部作用域中的a联系起来。我原以为需要显式指定参数捕获(即在第一个lambda中使用[a],在嵌套lambda中使用[&a])才能实现。

自动参数捕获的推断规则是什么?

1个回答

9
这在 [expr.prim.lambda.capture]p7 中有描述:
为了进行 lambda 捕获,表达式可能会如下引用本地实体:
- 命名局部实体的 id-expression 可能会引用该实体;命名一个或多个非静态类成员并且不形成成员指针([expr.unary.op])的 id-expression 可能会引用 *this。 - this 表达式可能会引用 *this。 - lambda-expression 可能会引用其 simple-captures 命名的局部实体。
如果一个表达式在可 odr 使用的声明区域内可能引用一个本地实体,并且如果忽略任何封闭的 typeid 表达式的影响,则该表达式可能被评估,则称该实体被每个介于其中的带有未显式捕获它的关联 capture-default 的 lambda-expression 隐式捕获。
换句话说:
如果使用需要定义,忽略 typeid 表达式,并且没有明确捕获,则在以下情况下 lambda 会隐式捕获:
- 命名变量;或者如果出现非静态类成员的名称(不包括指向成员的指针),则隐式捕获 *this;或 - 出现 this,则隐式捕获 *this 这些隐式捕获的实体被每个带有默认捕获的介于其中的 lambda 隐式捕获。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接