До сих пор, рассматривая лямбда-выражения C ++ в стиле c++11
, я поместил их все в две широкие категории: захват и отсутствие захвата.
Невозвратные лямбды, хотя и более ограничены в том, как их можно записать, гораздо более гибки в том, как их можно использовать - они могут неявно преобразовываться в аналогичные типы указателей на функции ;они не поощряют необоснованное std::function<…>
использование, их область применения менее вероятна выползти и вызывать побочные эффекты , и так далее.
Захватывающая лямбда, однако, может быть написана гораздо более широко.По общему признанию, они не предоставляют все те преимущества, которые я только что упомянул.Но захват лямбды компенсирует это большим спектром проблем, которые он может решить, выходя за пределы функции DAG прямого вызова стека с множеством форм доступа к окружающим областям.
Это, насколько я понимаю, однако.Когда я использую захват лямбд, я склонен явно ссылаться на определенные переменные, когда есть между одной и двумя необходимыми мне переменными:
using lambda_t = std::function<std::add_pointer_t<void>(int)>;
lambda_t lambda_explicit = [&one, &another](int descriptor) {
return ::mmap(nullptr, one, PROT_READ, MAP_PRIVATE, descriptor, another);
};
… если их больше двух, я предпочитаю (из равныхчасти синтаксического OCD и лени), чтобы избежать явно названных захватов в пользу формы ссылки на все:
lambda_t lambda_everything = [&](int descriptor) {
return ::mmap(nullptr, one, PROT_READ, MAP_PRIVATE, descriptor, another);
};
… которые отмечают, что изменение формы захватов лямбды не меняет ничего очевидного в лямбда-выраженияхtype - подпись вызова такая же, например.Это нелогично, так как кажется, что большая часть способа захвата работ неопределенно задана и в некоторой степени зависит от реализации , своего рода обратно пропорционально подробному формальному разнообразию, предоставляемому выражением захвата (или это декларация? Илисписок деклараций? ... Я не уверен) полную славу, которую вы увидите, если вы перейдете к этой последней ссылке и прокрутите немного вниз.
Я даже не коснулся подавляющего большинстваиз возможностей - я почти всегда просто делаю:
- Нет захвата вообще;
- Одна или две явно названные переменные, захваченные по ссылке;или
- Неизбирательный захват по ссылке всего:
[&]
Каковы обстоятельства, при которых я должен избегать использования одной формы захвата надДругой?
Какие формы особые, и их вообще следует избегать?Какие из них имеют ощутимые штрафы - в производительности, размере кода, потенциальной UB или что-то еще?Имеют ли какие-либо формы захвата ощутимые и / или легкие преимущества?