c++ - 自动参数捕获的推导规则是什么?

标签 c++ c++11 lambda template-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;
}

如我们所愿,输出是

nested lambda: a=20
a=10

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

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

最佳答案

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

For the purposes of lambda capture, an expression potentially references local entities as follows:

  • An id-expression that names a local entity potentially references that entity; an id-expression that names one or more non-static class members and does not form a pointer to member ([expr.unary.op]) potentially references *this.

  • A this expression potentially references *this.

  • A lambda-expression potentially references the local entities named by its simple-captures.

If an expression potentially references a local entity within a declarative region in which it is odr-usable, and the expression would be potentially evaluated if the effect of any enclosing typeid expressions ([expr.typeid]) were ignored, the entity is said to be implicitly captured by each intervening lambda-expression with an associated capture-default that does not explicitly capture it.

换句话说:

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

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

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

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

关于c++ - 自动参数捕获的推导规则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51759044/

相关文章:

c# - 在运行时创建通用类型的 Action<>

c++ - OpenCV : Using a Trimap image

c++ - 是否可以将所有权从 void* 转移到 unique_ptr?

c# - 匿名类型的属性列表

带有下划线的Python lambda作为参数?

c++ - 将 C++ 中的列表对象移动到另一个对象

c++ - jsoncpp 只写一个元素的json数组

c++ - 为什么我会从 cmath.h 中收到数百个语法错误?

c++ - 哪些 Boost 库是仅头文件?

c++ - 延长临时生命周期,适用于 block 范围的聚合,但不能通过 `new` ;为什么?