【发布时间】:2020-09-14 17:37:31
【问题描述】:
好的,这就是 n3337.pdf 中的 [expr.prim.lambda]p16 的直接内容。下面以代码为例:
int a = 1, b = 1, c = 1;
auto m1 = [a, &b, &c]() mutable
{
auto m2 = [a, b, &c]() mutable
{
std::cout << a << b << c; // Shouldn't this print 113 or 133?
a = 4; b = 4; c = 4;
};
a = 3; b = 3; c = 3;
m2();
};
a = 2; b = 2; c = 2;
m1();
std::cout << a << b << c; // Okay, this prints 234
并且它应该生成以下输出:
123234
但是,我理解 [expr.prim.lambda] 中文本的方式(这在某种程度上明显有缺陷),我觉得输出应该是113234,特别是b 的值打印在m2 .以下是我的理解/解释:
当std::cout << a << b << c; 在m2 内部执行时,根据 [expr.prim.lambda]p16(强调我的):
如果 lambda 表达式 m2 捕获了一个实体,并且该实体被直接封闭的 lambda 表达式捕获 m1,那么 m2 的捕获变换如下:
——如果m1通过副本捕获实体,则m2捕获m1闭包类型对应的非静态数据成员;
因此,m2 内的a 应将生成的成员捕获到闭包类型m1 中捕获的对应a。由于m1 中的a 按副本捕获,而m2 中的a 也按副本捕获,因此a 在m2 中的值应为1。
标准继续说(再次强调我的):
——如果 m1 通过引用捕获实体,则 m2 捕获由 m1 捕获的相同实体。
我相信这里的“同一实体”是指m1 通过引用捕获的实体,而当m2 捕获时,它应该是 - 如果是捕获,则引用同一实体通过引用,或者如果它是一个副本捕获它的副本。
因此,m2 中的 b 应指在两个 lambda 表达式之外定义的 b。那么m2 中b 的值应该是1,因为b 也是通过副本捕获的。
我哪里出错了?更具体地说,b 内的 m2 何时初始化?
【问题讨论】:
标签: c++ c++11 lambda language-lawyer