Хорошо, это сразу же из [expr.prim.lambda] p16 в n3337.pdf. Ниже приведен код в качестве примера:
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 (выделено мной):
Если лямбда-выражение m2 захватывает объект, и этот объект захватывается непосредственно включающим лямбда-выражением m1, тогда захват m2 преобразуется следующим образом:
- если m1 захватывает объект копией, m2 захватывает соответствующий non-stati c член данных типа закрытия m1;
Следовательно, a
внутри m2
должен захватывать член, сгенерированный в соответствующий a
, захваченный в закрытии наберите m1
. Поскольку a
в m1
захватывается копией, а a
в m2
также захватывается копией, значение a
в m2
должно быть 1
.
Стандарт идет чтобы сказать (опять же, выделено мной):
- если m1 захватывает объект по ссылке, m2 захватывает тот же объект , захваченный m1.
Я считаю, что « тот же объект » здесь относится к объекту, захваченному m1
посредством ссылки, а когда он захвачен m2
, он должен быть - ссылкой на тот же объект если это захват по ссылке, или его копия, если это захват по копии.
Следовательно, для b
в m2
следует ссылаться на b
, определенный вне обеих лямбда-выражений. Значение b
в m2
тогда должно быть 1
, поскольку b
также захватывается копией.
Где я ошибаюсь? В частности, когда инициализируется b
внутри m2
?