[C++] Подробное объяснение встроенного

Вечер понедельника, 28 августа 2023 г.


Оглавление


преимущество

Когда функция объявляется с inlineключевым словом, компилятор встраивает тело функции во все вызовы этой функции.

Это повышает эффективность выполнения, поскольку не требуются накладные расходы на вызов функции.

недостаток

Однако у чрезмерного использования встроенных функций есть и недостатки:

  1. Размер исполняемого файла увеличился. Исполняемые файлы становятся больше, поскольку тела функций копируются на каждый сайт вызова.
  2. Время компиляции увеличено. Компилятору необходимо обработать больше кода, поэтому время компиляции увеличивается.
  3. Возможности оптимизации сокращаются. Поскольку тело функции разбросано по нескольким местам, компилятору сложно ее оптимизировать.

Условия использования

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

В общем случае для встраивания подходят функции, удовлетворяющие следующим условиям:

  1. Тело функции небольшое (обычно не более 10 строк).
  2. Функция вызывается часто (накладные расходы на вызов относительно велики).
  3. Функции не вызывают себя рекурсивно.
  4. Тело функции не содержит сложных структур потока управления, таких как циклы и переходы.

Почему вызов функции имеет накладные расходы

Вызовы функций влекут за собой определенные накладные расходы, в основном в том числе:

  1. команда вызова. Для вызова функции требуется использование инструкции вызова, например callдирективы. Эта инструкция вызова заставляет программу перейти к телу функции и по возвращении вернуться к точке вызова. Эта операция перехода требует процессорного времени и памяти, что приводит к накладным расходам.

  2. Передача параметров. Передача параметров в функцию также требует времени и места, и необходимо скопировать фактическое значение параметра в формальный параметр или передать адрес фактического параметра формальному параметру.

  3. Обратный адрес сохраняется. После вызова функции необходимо сохранить адрес возврата, чтобы функция могла выполнить возврат. Хранение обратного адреса также требует места в стеке, что приводит к накладным расходам.

  4. Зарегистрируйтесь, сохраните. Перед вызовом функции значения соответствующих регистров необходимо сохранить в стек, чтобы тело функции не могло их изменить. Сохранение и восстановление значений регистров также требует времени и места.

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

Хотя эти накладные расходы относительно невелики для одного вызова функции, если функция вызывается часто, эти накладные расходы будут накапливаться и влиять на эффективность выполнения программы.

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

например

inline int add(int a, int b) { 
  return a + b; 
}

int main() {
  int sum = add(1, 2);
  // 这里,add()函数的函数体被内联,等价于:
  // int sum = 1 + 2; 
  // 函数调用开销被省略。
  return 0; 
}

Je suppose que tu aimes

Origine blog.csdn.net/m0_61629312/article/details/132550517
conseillé
Classement