Che*_*har 8 c++ lambda language-lawyer c++11
好的,这就是 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
Run Code Online (Sandbox Code Playgroud)
并且它将生成以下输出:
123234
但是,根据我理解 [expr.prim.lambda] 中文本的方式(显然存在某种缺陷),我觉得输出应该是113234,特别是b在m2. 以下是我的理解/解释:
Whenstd::cout << a << b << c;在 inside 中执行m2,根据 [expr.prim.lambda]p16(强调我的):
如果 lambda 表达式 m2 捕获了一个实体,并且该实体被直接封闭的 lambda 表达式 m1 捕获,则 m2 的捕获转换如下:
——如果m1通过复制捕获实体,则m2捕获m1的闭包类型对应的非静态数据成员;
因此,a内部m2应捕获生成的成员,以a在闭包类型中捕获相应的成员m1。由于ainm1通过复制捕获,并且ainm2也通过复制捕获,因此ina的值m2应该是1。
标准接着说(再次强调我的):
—如果 m1 通过引用捕获实体,则 m2 捕获由 m1捕获的同一实体。
我相信这里的“相同实体”是指m1通过引用捕获的实体,当被m2它捕获时应该是 - 如果是通过引用捕获,则是对同一实体的引用,如果是通过副本捕获,则是对同一实体的引用。
因此,binm2应指b两个 lambda 表达式之外的定义。bin m2then的值应该是1asb也被 copy 捕获。
我哪里错了?更具体地说,什么时候b内部m2初始化?
首先,请注意,根据C++11 [ expr.prim.lambda[] ] 第 14 段(或C ++17 [ expr.prim.lambda.capture] 第 10 段)。
您从 C++11 [expr.prim.lambda]/16 引用的部分(或 C++17 [expr.prim.lambda.capture]/13 中的相同内容)仅更改捕获的实体,而不更改捕获的实体的类型捕获。因此,在示例中,用于初始化的内部 lambda通过复制从原始定义中m2捕获。b
然后,注意 C++11 [expr.prim.lambda]/21:
当计算lambda 表达式时,复制捕获的实体用于直接初始化生成的闭包对象的每个相应的非静态数据成员。
(C++17 [expr.prim.lambda.capture]/15开头相同,但为init-capture语法添加了额外的措辞,如[var=init]。)
在该示例中,每次调用时都会对用于初始化的内部lambda 表达式m2求值,并初始化闭包对象的成员 for ,而不是按照lambda 表达式在代码中出现的顺序。由于 lambda for通过副本捕获原始值,因此它会获取调用时的值。如果多次调用,则每次的初始值可能不同。bm1.operator()m2bbm1m1b
| 归档时间: |
|
| 查看次数: |
318 次 |
| 最近记录: |