Вечер понедельника, 28 августа 2023 г.
Оглавление
преимущество
Когда функция объявляется с inline
ключевым словом, компилятор встраивает тело функции во все вызовы этой функции.
Это повышает эффективность выполнения, поскольку не требуются накладные расходы на вызов функции.
недостаток
Однако у чрезмерного использования встроенных функций есть и недостатки:
- Размер исполняемого файла увеличился. Исполняемые файлы становятся больше, поскольку тела функций копируются на каждый сайт вызова.
- Время компиляции увеличено. Компилятору необходимо обработать больше кода, поэтому время компиляции увеличивается.
- Возможности оптимизации сокращаются. Поскольку тело функции разбросано по нескольким местам, компилятору сложно ее оптимизировать.
Условия использования
inline
Ключевые слова следует использовать с осторожностью, а встраивание целесообразно только для небольших функций.
В общем случае для встраивания подходят функции, удовлетворяющие следующим условиям:
- Тело функции небольшое (обычно не более 10 строк).
- Функция вызывается часто (накладные расходы на вызов относительно велики).
- Функции не вызывают себя рекурсивно.
- Тело функции не содержит сложных структур потока управления, таких как циклы и переходы.
Почему вызов функции имеет накладные расходы
Вызовы функций влекут за собой определенные накладные расходы, в основном в том числе:
-
команда вызова. Для вызова функции требуется использование инструкции вызова, например
call
директивы. Эта инструкция вызова заставляет программу перейти к телу функции и по возвращении вернуться к точке вызова. Эта операция перехода требует процессорного времени и памяти, что приводит к накладным расходам. -
Передача параметров. Передача параметров в функцию также требует времени и места, и необходимо скопировать фактическое значение параметра в формальный параметр или передать адрес фактического параметра формальному параметру.
-
Обратный адрес сохраняется. После вызова функции необходимо сохранить адрес возврата, чтобы функция могла выполнить возврат. Хранение обратного адреса также требует места в стеке, что приводит к накладным расходам.
-
Зарегистрируйтесь, сохраните. Перед вызовом функции значения соответствующих регистров необходимо сохранить в стек, чтобы тело функции не могло их изменить. Сохранение и восстановление значений регистров также требует времени и места.
-
переключение контекста. При вызове функции необходимо переключиться между контекстом текущей функции и контекстом вызываемой функции, и эта операция переключения также влечет за собой накладные расходы.
Хотя эти накладные расходы относительно невелики для одного вызова функции, если функция вызывается часто, эти накладные расходы будут накапливаться и влиять на эффективность выполнения программы.
Короче говоря, причиной накладных расходов на вызовы функций являются время и пространство, необходимые для вызова инструкций, передачи параметров, хранения адреса возврата, сохранения регистров и переключения контекста. Использование 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;
}