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

Posted

技术标签:

【中文标题】自动参数捕获的推演规则是啥?【英文标题】: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])才能正常工作。

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

【问题讨论】:

【参考方案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 以默认捕获隐式捕获。

【讨论】:

以上是关于自动参数捕获的推演规则是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 VBA 函数调用中使用括号的规则是啥?

java引用类型的类型转换规则是啥?

keepalived启动后iptables自动添加Drop规则

$@ 在Linux Makefile中是啥意思

C语言双目运算符两边的运算数类型不一致系统自动转换的规则是啥?比如1.0/2=0.5那为啥不是1.0/2=0呢?

HTML在构造参数时遵循啥规则?