Имеет ли [=], что все локальные переменные будут скопированы?

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

void f()
{
    vector<int> v(10000);
    const int n = 5;
    const int DivByNCnt = count_if(istream_iterator<int>(cin), istream_iterator<int>(), 
          [=](int i)
          {
             return i % n == 0;
          });
}

Какое из следующего, если оно есть, истинно?

  • и n и v будут скопированы
  • n будет скопировано, v не будет
  • n будет скопирован, v может или не может быть скопирован в зависимости от настроек имплантации/оптимизации.

Предположим для аргумента, что конструктор векторной копии имеет побочные эффекты.

Ответ 1

Нет. Это просто означает, что все локальные переменные из области видимости доступны для поиска внутри тела лямбда. Только если вы ссылаетесь на имя локальной локальной переменной, эта переменная будет захвачена и будет зафиксирована по значению.

"Убрать что-нибудь" сокращает = и & - это просто синтаксический сахар, по существу, говоря компилятору "выяснить, что я имею в виду".


Формальная ссылка из 5.1.2/11-12:

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

Объект захватывается, если он зафиксирован явно или неявно.

Обратите внимание, что "capture-default" относится к [=] и [&]. Повторить, указав захват-дефолт, ничего не фиксирует; используется только odr-using переменная.

Ответ 2

Нет! (К счастью)

Вы можете запрограммировать свой код, чтобы проверить, действительно ли ваш компилятор это делает (или нет). Например, gcc 4.8.0 соответствует требованиям.


В соответствии с тем, что Стандарт фактически предусматривает (обращается назад):

§5.1.2/14 Сущность захватывается копией, если она неявно захвачена, а значение по умолчанию - = или если оно явно захвачено с захватом, который не включает &. Для каждого объекта, захваченного копией, в типе закрытия объявляется неназванный нестатический член данных.

$5.1.2/11 Если лямбда-выражение имеет связанный с захватом-умолчанию и его составной оператор odr-uses (3.2) this или переменную с автоматической продолжительностью хранения, а объект, использующий odr, явно не захвачен, то объект, использующий odr, называется неявным захватом; такие объекты должны быть объявлены в пределах охвата лямбда-выражения.

§5.1.2/9 Лямбда-выражение, наименьшей охватывающей областью которого является область блока (3.3.3), является локальным лямбда-выражением; любое другое лямбда-выражение не должно иметь список захвата в своем лямбда-интродукторе. Область достижения локального лямбда-выражения представляет собой набор охватывающих областей действия вплоть до самой внутренней охватывающей функции и ее параметров. [Примечание. Эта область охвата включает любые промежуточные лямбда-выражения. -end note]