首页 > 解决方案 > 当一个右值引用被副本捕获时会发生什么?

问题描述

如果我有

std::function<int()> &&x = [] { return 1; };
auto lambda = [y = x(), x] { 
    return y * x();
};

xinside lambda: std::function<int()>, std::function<int()>&or的类型是什么std::function<int()>&&?如果是第一个,捕获的x初始化是由移动构造函数还是由副本初始化的(我需要[y = x(), x = std::move(x)]移动它)?

标签: c++lambdac++14

解决方案


什么是x内部类型lambda

x被复制捕获,并且在闭包类型中声明的数据成员的类型将是std::function<int()>. [expr.prim.lambda.capture]/10

(强调我的)

对于通过副本捕获的每个实体,在闭包类型中声明了一个未命名的非静态数据成员。...如果实体是对对象的引用,则此类数据成员的类型是引用类型,...

x是由移动构造函数还是由副本初始化捕获的(我需要[y = x(), x = std::move(x)]移动它)?

是的,您必须x = std::move(x)明确编写,否则x将被复制构造,因为捕获的对象x本身就是一个左值。

以及为什么decltype(x)会导致 type std::function<int()>&&,因为x这里指的x是 lambda 之前定义的局部变量。[expr.prim.lambda.capture]/11

(强调我的)

lambda-expression 的复合语句中的每个 id-expression 是对由 copy 捕获的实体的 odr 使用,都被转换为对闭包类型的相应未命名数据成员的访问。

[注 7:不是 odr-use 的 id-expression 指的是原始实体,而不是闭包类型的成员。但是,这样的 id-expression 仍然会导致实体的隐式捕获。——尾注]

BTW(x)不是id 表达式x这里指的是闭包类型的成员。然后decltype((x))导致类型const std::function<int()> &(因为(x)它是一个左值表达式并且operator()lambda 是 const 限定的;对于mutablelambda 它将是std::function<int()> &)。


推荐阅读