Чи фіксують 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

Кожна змінна, прямо вказана у списку захоплення, фіксується. Захоплення за замовчуванням охоплює лише змінні, які обидві (а) не названі прямо у списку захоплення та (b), що використовуються в тілі виразу лямбда. Якщо змінна не має прямого імені, і ви не використовуєте змінну в лямбда-виразі, то змінна не фіксується. У вашому прикладі my_huge_vectorне захоплено.

За C ++ 11 §5.1.2 [expr.prim.lambda] / 11:

Якщо лямбда-вираз має асоційований за замовчуванням захоплення, а його з'єднання-оператор odr-use this або змінна з автоматичною тривалістю зберігання, а об'єкт, що використовується odr , не чітко зафіксований, тоді говорять, що використовується odr, називається суттєво захопленим.

Ваш лямбда-вираз має пов'язаний за замовчуванням захоплення: за замовчуванням ви захоплюєте змінні за значенням, використовуючи [=].

Якщо і лише якщо використовується змінна (у розумінні Правила одного визначення терміна "використовується"), це змінна фіксація неявно. Оскільки ви не використовуєте my_huge_vectorзовсім в тілі ("складене твердження") лямбда-виразу, він неявно фіксується.

Продовжувати §5.1.2 / 14

Суб'єкт охоплюється копією, якщо

  • він неявно фіксується, а за замовчуванням вловлювач є =або, якщо
  • він явно захоплюється захопленням, що не включає в себе &.

Оскільки ваш файл my_huge_vectorне зафіксовано неявно і не є чітко зафіксованим, він не захоплюється взагалі, копією чи посиланням.


10
Чи є у вас Свята котировка?
GManNickG

Я, однак, скажу, що цілий п. 5.1.1 важливий для розуміння всіх деталей. У цьому розділі визначено багато технічних термінів, і тому що визначення різних компонентів лямбда-виразів обов'язково заплутуються, важко витягнути короткі цитати, які остаточно говорять "це X і тому X."
James McNellis

Pinging за увагу тут , який говорить , що така оптимізація не допускається, по крайней мере, явно названих змінних. Я не впевнений, де провести лінію.
GManNickG

@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 dp, не хвилюйтесь, MSVC досі залишається купою смердючих лайно сьогодні. пор. godbolt.org/z/vHnnCX (перевірити в gcc на лулз). Це сказав; Я не розумію, чому будь-який ідентифікатор, що з’являється в оціненому виразі, не буде використовуватися ODR. Я думаю, що цей випадок, безумовно, використовується ODR, якщо ви не маєте на увазі, що він може бути інтерпретований як constexpr, тому корисне лише значення? Я не впевнений, що компілятор припускає, що constречі потенційно не мутують. якщо, можливо, супер агресивний прапор оптимізації OX або інше.
v.oddou
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.