#c #lambda
Вопрос:
У меня есть функция, которая объявляет некоторые локальные лямбда-переменные, и я хочу составить их в другой лямбде. Простой пример:
auto aggressiveModel = [this](const Paramsamp; params) -gt; double { ... }; auto lazyModel = [this](const Paramsamp; params) -gt; double { ... }; auto model = [ ((???))aggressiveModel, ((???))lazyModel](const Paramsamp; params) { return std::min(aggressiveModel(params), lazyModel(params)); };
В model(...)
лямбде следует ли захватывать другие лямбды по значению, ссылке или по умолчанию? Что означают спецификаторы в контексте переменных lamba?
Комментарии:
1. Собираетесь ли вы возвращаться
model
за пределы области, в которой он объявлен?2. @NathanOliver В данном случае нет, но я ищу более общие рекомендации, чтобы понять, что означает захват в контексте ламбас.
3. Тогда в этом случае я бы предложил захватить по ссылке. В целом, однако, если лямбда может пережить то, что вы фиксируете по ссылке, то вы должны фиксировать по значению, иначе у вас может быть висячая ссылка.
4. Они означают то же самое, что и в контексте не-лямбд. Лямбды не являются чем-то особенным.
5. Захват лямбды на самом деле является объектом, являющимся сценами, подумайте об этом таким образом. Применяются те же правила определения области действия и срока службы.
Ответ №1:
Лямбды-это просто более простые способы написания функторов объектов в старом стиле. aggressiveModel
эквивалентно:
struct AggressiveModel { AggressiveModel(Object* _this) : _this(_this) { } Object* _this; double operator()(const Paramsamp; params) { ... } }; AggressiveModel aggressiveModel(this);
aggressiveModel
поэтому копирование-это просто вопрос копирования захваченной this
переменной, а не то, о чем вам следует беспокоиться. Очевидно, что лямбда с более длинным списком захвата или с более дорогими для копирования объектами будет отличаться. Хотя даже в этом случае компилятор может оптимизировать копии, особенно если mutable
это не так, и компилятор, следовательно, знает, что ни одно из значений не изменится, и это может доказать, что исходная лямбда не выходит за рамки.
Как и в случае с любым другим объектом, использование ссылки на лямбду позволит избежать копирования, но вы должны убедиться, что объект остается в области действия в течение всего срока действия ссылки.