Например, у меня есть следующий код:
auto z = [](int x) -> int {
if (x > 0) {
switch (x) {
case 2: return 5;
case 3: return 6;
default: return 1;
}
}
return 0;
};
И позже я звоню это несколько раз. В коде asm я вижу внешние вызовы с лямбдой .... что-то ... Это становится не так легко читать, и я думаю, что это также может привести к производительности. Может быть, я выиграл в метапрограммировании, но проиграл ли я в отладке и производительности asm? Должен ли я избегать возможностей современного языка, макросов и других аспектов метапрограммирования, чтобы быть уверенным в производительности и простоте отладки?
if
полностью избыточен в коде примера, и хотя компилятор, вероятно, поймает, что нет причин искушать неверный прогноз ветвления.Ответы:
Нет , не тогда, когда вы пишете свой код в первый раз и не страдаете от реальных, измеримых проблем с производительностью. Для большинства задач это стандартный случай. Слишком рано думать об оптимизации называют «преждевременной оптимизацией», и есть веские причины, по которым Д. Кнут назвал это «корнем всего зла» .
Да , когда вы измеряете реальное, доказуемое узкое место в производительности и определяете именно эту лямбда-конструкцию как основную причину. В этом случае может быть хорошей идеей вспомнить «закон утечек абстракций» Джоэла Спольски и подумать о том, что может произойти на уровне ассемблера. Но будьте осторожны, вы можете быть удивлены, насколько незначительным будет увеличение производительности, когда вы заменяете лямбда-конструкцию «не очень современной» языковой конструкцией (по крайней мере, при использовании достойного компилятора C ++).
источник
Выбор между лямбда-классом и функтором является компромиссом.
Выигрыш от лямбды в основном синтаксический, сводя к минимуму количество шаблонного кода и позволяя концептуально связанному коду быть встроенным внутри функции, которая будет его использовать (немедленно или позже).
С точки зрения производительности это не хуже, чем класс функторов , который является структурой или классом C ++, который содержит один «метод». Фактически, компиляторы обрабатывают лямбду не иначе, как сгенерированный компилятором класс функторов за сценой.
В вашем примере кода с точки зрения производительности он ничем не отличается от вызова функции, потому что у этого класса функтора нет состояния (поскольку он содержит пустое предложение захвата), поэтому не требуется никакого выделения, конструктора или уничтожения.
Отладка любого нетривиального кода C ++ с использованием дизассемблера всегда была сложной задачей. Это верно с использованием лямбды или без нее. Это вызвано сложной оптимизацией кода компилятором C ++, которая привела к переупорядочению, перемежению и удалению мертвого кода.
Аспект искажения имен несколько неприятен, и поддержка лямбды в отладчике все еще находится в зачаточном состоянии . Можно только надеяться, что поддержка отладчика со временем улучшится.
В настоящее время наилучшим способом отладки лямбда-кода является использование отладчика, который поддерживает установку точек останова на уровне исходного кода, т.е. путем указания имени исходного файла и номера строки.
источник
Чтобы добавить к ответу @DocBrown, помните, что в наши дни центральные процессоры дешевы, но рабочая сила стоит дорого.
В общей стоимости программы аппаратное обеспечение обычно тривиально по сравнению со стоимостью обслуживания, которое является самой дорогой частью типичного проекта (даже больше, чем его разработка).
Следовательно, ваш код должен оптимизировать обслуживание превыше всего, кроме тех случаев, когда производительность критична (и даже в этом случае необходимо учитывать обслуживание).
источник