Захватывают ли лямбда-выражения c ++ 11 переменные, которые они не используют?


124

Когда я использую, [=]чтобы указать, что я хотел бы, чтобы все локальные переменные были захвачены по значению в лямбде, приведет ли это к тому, что все локальные переменные в копируемой функции или только все локальные переменные , которые используются лямбда ?

Так, например, если у меня есть:

vector<int> my_huge_vector(100000);
int my_measly_int;
some_function([=](int i){ return my_measly_int + i; });

Будет ли скопирован my_huge_vector, даже если я не использую его в лямбде?

Ответы:


115

Каждая переменная, явно указанная в списке захвата, фиксируется. При захвате по умолчанию будут захватываться только те переменные, которые (а) явно не названы в списке захвата и (б) используются в теле лямбда-выражения. Если переменная явно не названа и вы не используете ее в лямбда-выражении, то переменная не фиксируется. В вашем примере my_huge_vectorне фиксируется.

Согласно C ++ 11 §5.1.2 [expr.prim.lambda] / 11:

Если лямбда-выражение имеет связанный захват по умолчанию и его составной оператор odr-uses this или переменную с автоматической продолжительностью хранения, а объект odr-used не захвачен явно, то считается, что объект odr-used захватывается неявно.

У вашего лямбда-выражения есть связанный захват по умолчанию: по умолчанию вы захватываете переменные по значению с помощью [=].

Если и только если используется переменная (в смысле термина «использованный» в соответствии с одним правилом определения), это переменная неявно фиксируется. Поскольку вы вообще не используете my_huge_vectorв теле («составной оператор») лямбда-выражения, оно не фиксируется неявно.

Чтобы продолжить с §5.1.2 / 14

Сущность захватывается копией, если

  • он неявно захватывается, а захват по умолчанию - =или если
  • он явно захватывается с захватом, который не включает &.

Поскольку ваш my_huge_vectorобъект не фиксируется неявно и не фиксируется явно, он вообще не фиксируется ни копией, ни ссылкой.


10
У тебя есть Священная цитата?
GManNickG

Я скажу, однако, что §5.1.2 в целом важен для понимания всех деталей. В этом разделе определено множество технических терминов, и, поскольку определения различных компонентов лямбда-выражений обязательно запутаны, трудно выделить короткие кавычки, которые однозначно говорят: «Это X, и именно поэтому X».
Джеймс МакНеллис

Pinging за внимание здесь , который говорит , что такая оптимизация не допускается, по крайней мере, явно названных переменных. Я не уверен, где провести черту.
GManNickG 03

@GManNickG: Это отличный троллинг ;-). Мне потребовалось три добрых щелчка по этой ссылке, прежде чем я понял, что она действительно указывает на эту страницу ...: -O [В любом случае, я перечитаю спецификацию языка, когда приду в офис завтра утром, и обновлю ответ соответствующий.]
Джеймс МакНеллис

Вот дерьмо, прости !!! Мой вопрос был дан ответ, я имел в виду , чтобы связать здесь вместо этого. Должно быть, это было ужасно запутанно.
GManNickG

16

Нет, my_huge_vectorсниматься не будут. [=]означает, что все используемые переменные фиксируются в лямбде.


6
Ага. Обратите внимание , что используется это технический термин, хотя и на самом деле означает одно определение Правило используется . Так, например, рассмотрим 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 или прочее.
v.oddou
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.