«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Почему компилятор оптимизирует лямбда-функции более эффективно, чем традиционные функции?

Почему компилятор оптимизирует лямбда-функции более эффективно, чем традиционные функции?

Опубликовано 19 ноября 2024 г.
Просматривать:214

Why does the compiler optimize lambda functions more effectively than traditional functions?

Лямбда-оптимизация и встроенные функции: преимущество компилятора

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

Функциональные объекты и встраивание

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

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

Экземпляры шаблонов: исследование различий

Чтобы проиллюстрировать это несоответствие, рассмотрим шаблон функции карты:

template 
void map(Iter begin, Iter end, F f) {
    for (; begin != end;   begin)
        *begin = f(*begin);
}

Вызов с помощью лямбды:

int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });

приводит к созданию индивидуального экземпляра:

template 
void map(int* begin, int* end, _some_lambda_type f) {
    for (; begin != end;   begin)
        *begin = f.operator()(*begin);
}

Компилятор идентифицирует функцию _some_lambda_type::operator() и может напрямую встраивать к ней вызовы. Каждый отдельный тип лямбды вызывает новый экземпляр карты, гарантируя оптимизацию для конкретной лямбды.

Напротив, вызов карты с указателем на функцию приводит к следующему экземпляру:

template 
void map(int* begin, int* end, int (*f)(int)) {
    for (; begin != end;   begin)
        *begin = f(*begin);
}

Здесь указатель функции f указывает на разные адреса для каждого вызова карты, что запрещает встроенную оптимизацию. Вызов Map должен быть встроен, чтобы компилятор мог преобразовать f в конкретную функцию.

Таким образом, особенность лямбда-выражений как функциональных объектов и их способность облегчать создание экземпляров шаблонов предоставляют компиляторам большие возможности оптимизации, чем вызовы традиционных функций. через указатели.

Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3