С++ 11 lambda: смешанный список захвата
Может ли кто-нибудь, пожалуйста, показать мне следующие примеры:
1) Лямбда, которая фиксирует x
по значению. y
по ссылке. Что остальное по умолчанию, если не указано?
2) Лямбда, которая фиксирует x
по значению. y
по ссылке, все остальное по значению.
3) Лямбда, которая фиксирует x
по значению. y
по ссылке, все остальное по ссылке.
Кроме того, разрешено ли, что 2 лямбда в одном и том же объеме имеют одну и ту же подпись захвата, например, оба являются []
или оба являются [& x, =]
благодаря
Ответы
Ответ 1
1) [x, &y](){}
остался не захвачен
2) [=, &y](){}
3) [&, x](){}
Список захвата представляет собой список с нулевым или большим количеством символов, разделенный запятыми, необязательно начинающийся с по умолчанию для захвата. Единственными значениями по умолчанию для захвата являются & (по ссылке) и = (по значению). Если используется захват по умолчанию, никакие другие записи не могут использовать один и тот же тип захвата. Любой захват может появляться только один раз.
Кроме того, разрешено ли, что 2 лямбда в одном и том же объеме имеют одну и ту же подпись захвата, например, оба являются [] или оба являются [& x, =]
Конечно, это разрешено. Каждая лямбда будет отдельным объектом и имеет свой особый тип. Если вы возьмете переменную по значению в два лямбда, то каждая лямбда будет иметь свою копию. Если вы возьмете переменную по ссылке в два лямбда, то каждая лямбда будет иметь ссылку на одну и ту же захваченную переменную.
Ответ 2
Можно просто написать несколько примеров:
int x = 7, y = 12, z = 24;
auto lambda1 = [x, &y]{
// can't do this...
// std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
std::cout << "x=" << x << ", y=" << y << std::endl;
};
auto lambda2 = [=, x, &y]{
std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
};
auto lambda3 = [&, x, &y]{
std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl;
};
++x, ++y, ++z;
lambda1();
lambda2();
lambda3();
Теперь lambda1
здесь не может использовать z
. Там нет "неявного" захвата, так как мы не имеем =
или &
указание и z
не отображается в списке захвата, мы не можем напечатать z
там. Так что ошибка, если мы попытаемся использовать эту строку, я прокомментировал.
Остальные два являются точными и будут печатать 7, 13, 24 и 7, 13, 25 соответственно. Обратите внимание, что the =
и &
должны быть первыми. Кроме того, учитывая, что мы захватываем все по значению/ссылке, один из других захватов является избыточным, поэтому мы могли бы сделать:
auto lambda2 = [=, &y]{ ... };
auto lambda3 = [&, x]{ ... };
Ответ 3
1)
[x,&y](){} // the rest is not captured, eg 'z' is not defined in the scope
2)
[=,&y](){} // '=' is capture everything by value
3)
[&,x](){} // '&' is capture everything by reference
Ответ 4
Чтобы процитировать Bjarne из его С++ 11 FAQ:
[&] - это "список захвата", указывающий, что используемые локальные имена будут передаваться по ссылке. Мы могли бы сказать, что мы хотели "захватить" только v, мы могли бы сказать так: [& v]. Если бы мы хотели передать v по значению, мы могли бы сказать так: [= v]. Захват ничего не равен [], захват всех по ссылкам [&], а захват по значению - [=]. Если действие не является обычным и простым, я рекомендую использовать именованный функциональный объект или функцию.