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

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

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 может быть скопировано или не скопировано в зависимости от настроек реализации/оптимизации.

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


person Armen Tsirunyan    schedule 25.03.2013    source источник
comment
Ничего не зная о семантике С++ 11, все, кроме захваченного n, было бы полным безумием по отношению к семантике любого другого языка с первоклассными анонимными функциями и правильными замыканиями.   -  person Gian    schedule 25.03.2013


Ответы (2)


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

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


Официальная ссылка из 5.1.2/11-12:

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

Сущность захвачена, если она захвачена явно или неявно.

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

person Kerrek SB    schedule 25.03.2013
comment
Я не сомневаюсь, что вы правы, но есть ли у вас ссылки? - person Alex Chamberlain; 25.03.2013
comment
@AlexChamberlain: см. 5.1.2/11-12 о неявном и явном захвате. Это использование переменных внутри тела лямбды, которое выполняет захват. - person Kerrek SB; 25.03.2013

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

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


Что касается того, что на самом деле требует Стандарт (работая в обратном направлении):

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

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

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

person Matthieu M.    schedule 25.03.2013
comment
MSVC 10.0 не копирует v, но я хотел знать, есть ли гарантия, что v не будет скопирован! - person Armen Tsirunyan; 25.03.2013
comment
@ArmenTsirunyan: Я добавил соответствующие цитаты Стандарта. Согласно §5.1.2/14, только захваченные члены должны размещаться в типе замыкания. - person Matthieu M.; 25.03.2013