【问题标题】:What are the deduction rules for automatic argument capture?自动参数捕获的推演规则是什么?
【发布时间】:2018-08-09 04:49:53
【问题描述】:

我之前看到了与此代码等效的代码,得知它按预期工作时我有点惊讶:

#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 之间建立连接。我认为参数捕获需要明确(即第一个 lambda 中的[a],嵌套中的[&amp;a])才能正常工作。

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

【问题讨论】:

    标签: c++ c++11 lambda template-argument-deduction


    【解决方案1】:

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

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

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

    • this 表达式可能引用 *this

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

    如果一个表达式潜在地引用了一个声明区域内的一个本地实体,在该区域内它是 odr 可用的,并且如果任何封闭的 typeid 表达式 ([expr.typeid]) 的影响被忽略,则该表达式可能会被评估,据说该实体被每个干预 lambda-expression 隐式捕获,并带有一个未显式捕获它的关联 capture-default

    换句话说:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2021-06-20
      • 1970-01-01
      • 2023-01-14
      • 2017-01-12
      • 2022-01-05
      • 2015-06-23
      • 2014-08-12
      • 1970-01-01
      • 2016-08-07
      相关资源
      最近更新 更多