Страницы

Поиск по вопросам

понедельник, 15 октября 2018 г.

Список захвата в лямбда-функциях: есть ли смысл захватывать все переменные?

Внутри квадратных скобок в определении лямбда-функции можно задать переменные из внешнего контекста, которые нужны для работы этой лямбда функции. Можно их перечислить вручную, а можно просто задать захват всех переменных сразу:
auto lambda1 = [x](int a) {return a < x; }; // Список захвата задан вручную auto lambda2 = [&](int a) {return a < x; }; // Тупо захватываем всё по ссылке
Собственно вопрос: при каких условиях какой вариант предпочтителен? Есть ли вообще смысл заморачиваться и указывать список захвата вручную, может быть проще всегда писать [&] и не напрягать мозг, компилятор всё и так оптимизирует?


Ответ

При захвате переменной по ссылке существует опасность что ссылка в итоге проживет дольше чем переменная, поэтому такого варианта надо избегать при работе с долгоживущими лямбдами.
Кроме того, при использовании варианта "захват всего по значению", он же [=] есть риск получить циклическую ссылку или еще какую-нибудь ерунду по невнимательности.
Поэтому для долгоживущих лямбд надо всегда явно указывать список захватываемых переменных:
auto lambda1 = [x](int a) { return a < x; };
С другой стороны, если время жизни лямбды не превышает одного оператора в вашем коде - то захват всего по ссылке не сделает ничего страшного.
Так, например, известно что std::for_each не сохраняет переданный ему функтор никуда:
std::for_each(c.begin(), c.end(), [&](int a) { if (a < x) { std::cout << a << std::endl; } });

Комментариев нет:

Отправить комментарий