Из оконная процедура, Я пишу switch
оператор, использующий самодельные лямбды, например:
LRESULT CALLBACK proc (HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { переключатель (сообщение) { case WM_CREATE: return [] (WPARAM wp, LPARAM lp) { do_something (wp, lp); вернуть 0; } (wp, lp); case WM_SIZE: return [] (HWND hWnd) { do_another_thing (HWND); вернуть 0; } (HWND); } return DefWindowProc (hWnd, msg, wp, lp); }
Я полагаю, что компиляторы могут оптимизировать его в значительной степени так, как они хотят, но, вообще говоря, добавит ли компилятор много стандартного кода к этому, по сравнению с тем, что эти лямбды не используются?
Может ли компилятор обнаружить избыточные лямбды и удалить их?
Подобные вопросы по оптимизации не имеют однозначного ответа в том смысле, что оптимизатор совместимого компилятора может делать много-много вещей. Однако в этом случае большинство современных оптимизаторов почти наверняка собираются встроить лямбду и генерировать ту же сборку независимо от того, используете ли вы лямбду или нет. Поскольку лямбды имеют уникальный тип, компилятор Можно встроить легко. Поскольку лямбда объявляется и немедленно используется и никогда не назначается (более распространенное имя — «немедленно вызывается / оценивается лямбда, а не« самостоятельно выполняется »), компилятор знает, что он может быть вызван только один раз. Поэтому, как правило, он принимает решение встроить.
Чтобы быть уверенным, вы можете посмотреть на некоторые сборки: https://godbolt.org/g/QF6WmR. Как вы можете видеть, сгенерированная сборка в этом конкретном примере идентична, но, очевидно, она не доказывает общий случай.
В общем, лямбда-символы в C ++ считаются абстракциями с низкой или нулевой стоимостью. Если вы считаете, что лямбда-код делает код максимально чистым, используйте его. Если вам нужно, вы всегда можете быстро убедиться, что сборка одинакова. Ваша причина использовать лямбду таким образом немного необычна; Я бы не стал считать свертывание кода хорошей причиной. Более распространенная причина использовать лямбды, оцененные немедленно, — это возможность использовать const
в ситуациях, когда иначе вы не можете:
int x;
try {
x = foo();
}
catch (const ExceptionType& e) {
x = bar();
}
против
const auto x = [] () {
try {
return foo();
}
catch (const ExceptionType& e) {
return bar();
}
}();
Настаивать x
во внешней области в традиционном коде C ++ мы должны сначала объявить его, а затем присвоить ему. Используя лямбду, которая возвращает желаемое значение, мы можем объявить и назначить x
в то же время, позволяя ему быть const
,
Вопрос немного странный. Компилятор не «удаляет» лямбды, потому что лямбды в вашем исходный код, и компилятор не изменяет ваш исходный код. Он генерирует машинный код, который отображает поведение программы, которую вы выразили в исходном коде.
Компилятор может свободно генерировать столько машинного кода, сколько ему захочется, до тех пор, пока результат ведет себя так, как выражает ваша программа.
Компилятору, конечно, не нужно выдавать отдельные тела функций и переходить между ними, если это возможно в соответствии весь код в одном месте, и это обычно применяемая оптимизация.