Подтвердить что ты не робот

Являются ли lambdas встроенными, как функции в С++?

Может ли/встроить лямбда-функции компилятора для повышения эффективности, как это могло бы быть с простыми стандартными функциями?

например.

std::vector<double> vd;
std::for_each(vd.begin(), vd.end(), [](const double d) {return d*d;});

Или есть потеря эффективности, вызванная отсутствием оптимизации?

Второй вопрос: где я могу проверить, использует ли компилятор оптимизированные вызовы встроенных функций, которые отправляются алгоритму? Я имею в виду, что если функция, а не объект функции, отправляется алгоритму, последний получает указатель на эту функцию, а некоторые компиляторы оптимизируют указатели на встроенные функции, а другие нет.

4b9b3361

Ответ 1

В простых случаях, например, в вашем примере , вы должны ожидать повышения производительности с помощью lambdas, чем с указателями функций, см.

Почему лямбды лучше оптимизируются компилятором, чем простые функции?

Как уже указывали другие, нет гарантии, что ваш звонок будет включен, но у вас есть лучшие шансы с лямбдами. Одним из способов проверки того, был ли вызов включен, является проверка сгенерированного кода. Если вы используете gcc, передайте флаг -S в компилятор. Конечно, он предполагает, что вы можете понять код сборки.

Ответ 2

Во-первых: вся точка дизайна lambdas на С++ заключается в том, что у них нет накладных расходов по сравнению с вызовами функций. Это, в частности, связано с тем, что призывы к ним могут быть встроены.

Но здесь возникает путаница понятий: "inline" - это связь функции, т.е. это утверждение о том, как определяется функция, а не как ее вызвать. Но функции, которые определены в строке, могут быть полезны при оптимизации компилятора, с помощью которой вызовы таких функций встроены. Это разные, но очень близкие понятия.

Теперь, в случае lambdas, фактическая функция - это operator(), которая определена inline в анонимном классе. Прямые вызовы лямбда являются прямыми вызовами ее operator() и поэтому могут быть встроены.

Ответ 3

Это зависит от уровня оптимизации, данного компилятору. Возьмем, к примеру, эти две функции, которые семантически идентичны. Один из них - стиль С++ 11, другой стиль C.

void foo1 (void)
{
    int arr[100];
    std::generate(std::begin(arr), std::end(arr), [](){return std::rand()%100;});
}

void foo2 (void)
{
    int arr[100];
    for (int *i = arr; i < arr+100; i++) *i = std::rand()%100;
}

Компиляция этого с gcc -O4 испускает код, который очень похож (не идентичный, но эквивалентный уровень сложности) для двух функций.

Однако при компиляции unoptimised lambda не является встроенной (и не являются вызовами std:: begin и std:: end).

Итак, хотя компилятор может (и делает) отлично справляться с оптимизацией кода современного стиля, когда его просят сделать это, возможно, или, вероятно, это будет штраф за производительность для этого типа кода в неоптимизированной сборке отладки.