Захватывают ли лямбда-выражения c ++ 11 переменные, которые они не используют?
124
Когда я использую, [=]чтобы указать, что я хотел бы, чтобы все локальные переменные были захвачены по значению в лямбде, приведет ли это к тому, что все локальные переменные в копируемой функции или только все локальные переменные , которые используются лямбда ?
Каждая переменная, явно указанная в списке захвата, фиксируется. При захвате по умолчанию будут захватываться только те переменные, которые (а) явно не названы в списке захвата и (б) используются в теле лямбда-выражения. Если переменная явно не названа и вы не используете ее в лямбда-выражении, то переменная не фиксируется. В вашем примере my_huge_vectorне фиксируется.
Согласно C ++ 11 §5.1.2 [expr.prim.lambda] / 11:
Если лямбда-выражение имеет связанный захват по умолчанию и его составной оператор odr-usesthis или переменную с автоматической продолжительностью хранения, а объект odr-used не захвачен явно, то считается, что объект odr-used захватывается неявно.
У вашего лямбда-выражения есть связанный захват по умолчанию: по умолчанию вы захватываете переменные по значению с помощью [=].
Если и только если используется переменная (в смысле термина «использованный» в соответствии с одним правилом определения), это переменная неявно фиксируется. Поскольку вы вообще не используете my_huge_vectorв теле («составной оператор») лямбда-выражения, оно не фиксируется неявно.
Чтобы продолжить с §5.1.2 / 14
Сущность захватывается копией, если
он неявно захватывается, а захват по умолчанию - =или если
он явно захватывается с захватом, который не включает &.
Поскольку ваш my_huge_vectorобъект не фиксируется неявно и не фиксируется явно, он вообще не фиксируется ни копией, ни ссылкой.
Я скажу, однако, что §5.1.2 в целом важен для понимания всех деталей. В этом разделе определено множество технических терминов, и, поскольку определения различных компонентов лямбда-выражений обязательно запутаны, трудно выделить короткие кавычки, которые однозначно говорят: «Это X, и именно поэтому X».
Джеймс МакНеллис
Pinging за внимание здесь , который говорит , что такая оптимизация не допускается, по крайней мере, явно названных переменных. Я не уверен, где провести черту.
GManNickG 03
@GManNickG: Это отличный троллинг ;-). Мне потребовалось три добрых щелчка по этой ссылке, прежде чем я понял, что она действительно указывает на эту страницу ...: -O [В любом случае, я перечитаю спецификацию языка, когда приду в офис завтра утром, и обновлю ответ соответствующий.]
Джеймс МакНеллис
Вот дерьмо, прости !!! Мой вопрос был дан ответ, я имел в виду , чтобы связать здесь вместо этого. Должно быть, это было ужасно запутанно.
GManNickG
16
Нет, my_huge_vectorсниматься не будут. [=]означает, что все используемые переменные фиксируются в лямбде.
Ага. Обратите внимание , что используется это технический термин, хотя и на самом деле означает одно определение Правило используется . Так, например, рассмотрим void f() { const int size(10); [] { int x[size]; }; }. Здесь sizeне фиксируется, но это нормально, потому что он не используется в смысле ODR. (Visual C ++ 2010 не принимает этот код либо потому, что спецификация изменилась после выпуска VC10, либо из-за ошибки, предположительно это будет исправлено в следующей версии; g ++ 4.5.1 принимает это.)
Джеймс МакНеллис
@JamesMcNellis, не волнуйтесь, MSVC по сей день остается грудой вонючего дерьма. ср godbolt.org/z/vHnnCX (проверьте gcc для lulz). Тем не менее; Я не понимаю, почему любой идентификатор, появляющийся в оцениваемом выражении, не будет использоваться ODR. Я думаю, что этот случай определенно используется ODR, если вы не имеете в виду, что он может быть интерпретирован как constexpr, поэтому полезно только значение? Я не уверен, что компилятор предполагает, что constвещи потенциально не видоизменяются. разве что сверхагрессивный флаг оптимизации OX или прочее.
Нет,
my_huge_vector
сниматься не будут.[=]
означает, что все используемые переменные фиксируются в лямбде.источник
void f() { const int size(10); [] { int x[size]; }; }
. Здесьsize
не фиксируется, но это нормально, потому что он не используется в смысле ODR. (Visual C ++ 2010 не принимает этот код либо потому, что спецификация изменилась после выпуска VC10, либо из-за ошибки, предположительно это будет исправлено в следующей версии; g ++ 4.5.1 принимает это.)const
вещи потенциально не видоизменяются. разве что сверхагрессивный флаг оптимизации OX или прочее.