Имеет ли [=], что все локальные переменные будут скопированы?
Когда я пишу лямбда с [=]
, означает ли это, что все мои локальные переменные будут скопированы в члены созданной структуры или я могу предположить, что только те, которые действительно используются в лямбда? Например:
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]