C добавлено встроенное ключевое слово, которое может префикс определения функции, например:
inline int max_int( int a, int b ) { return a > b ? a : b; }
, чтобы дать компилятору «подсказку», что программа в целом может повысить производительность за счет встроенной функции.
Код функции, которая была встроена, расширялась в каждой точке ее вызова вместо выполнения обычного механизма вызова функции:
Для очень маленьких функций встраивание может дать прирост производительности. Но, как и во всем остальном, здесь есть компромиссы.
Ключевое слово inline было перенесено на C99, но с немного другими требованиями — об этом позже.
Встроенные функции подобны (и предназначены для замены многих видов использования) функциональных макросов. В целом это хорошо, поскольку встроенные функции являются функциями и имеют полную семантику функций, а не простую замену текста, выполняемую препроцессором, который не понимает ни C, ни C .
Макрос, эквивалентный функции max_int():
#define MAX_INT(A,B) A > B ? A : B /* bad implementation */
имеет следующие проблемы:
Дополнительно макрос:
Встроенные функции не имеют ни одной из этих проблем, но могут обеспечить такой же выигрыш в производительности. Следовательно, используйте встроенные функции вместо функциональных макросов.
Как уже упоминалось, указание встроенной функции — это только «подсказка» компилятору о том, что программа в целом может выиграть в производительности от встроенной функции. Компилятор может игнорировать подсказку.
Почему? Потому что бывают случаи, когда это либо не очень хорошая идея, либо невозможно. Функция либо не является встроенной, либо обычно не является встроенной, если выполняется одно из следующих условий:
Могут быть и другие причины. Все это сильно зависит от функции, ее аргументов, компилятора и любых предоставленных ей опций.
Если компилятор либо не может, либо предпочитает не встраивать функцию, он не предупреждает вас, что он этого не сделал (по умолчанию). Некоторые компиляторы, например, gcc, имеют опцию -Winline, которая предупредит вас и сообщит причину, по которой функция не была встроена.
Указание inline аналогично указанию регистра в старом коде — оба они являются лишь подсказками.
Для большинства функций основная часть затрат на выполнение функции приходится на тело функции, а не на механизм вызова функции. Следовательно, чтобы функция была хорошим кандидатом на встраивание, она обычно должна быть:
Если сомневаетесь, профилируйте свой код. Использование inline — это не волшебное ключевое слово «сделай меня быстрее». Кроме того, чрезмерное использование встроенных функций может привести к раздуванию кода, что дополнительно приведет к ухудшению производительности вашей программы в целом.
Подробнее см. в разделе «Встроенная болезнь».
К функциям, которые часто являются хорошими кандидатами на встраивание, относятся:
Идеальная встроенная функция. увеличивает производительность, и уменьшает размер кода.
Однако есть одно предостережение относительно любой встроенной функции: если ее определение изменится, потребуется перекомпиляция всего кода, который ее использует.
Если встроенная функция фактически встроена компилятором, то, помимо исключения кода обычного механизма вызова функций, компилятор также может:
Чтобы компилятор мог встроить функцию, он должен иметь возможность «видеть» ее определение (а не только ее объявление) в каждом файле .c или .cpp, в котором он используется. точно так же, как макрос. Следовательно, встроенная функция должна быть определена в заголовочном файле.
Обычно функция, как и все остальное, должна иметь ровно одно определение, придерживаясь правила одного определения (ODR). Однако, поскольку определение встроенной функции «видно» в нескольких файлах .c или .cpp, ODR для этой функции приостанавливается.
Можно иметь разные определения для встроенных функций с одинаковым именем, но это приводит к неопределенному поведению, поскольку у компилятора нет возможности проверить, что все определения одинаковы.
Чтобы встроить функцию в C, все, что вам нужно сделать, это поставить перед определением функции префикс inline — вот и все. Компилятор и/или компоновщик автоматически удалит все определения из конечного исполняемого файла, кроме одного.
Однако, чтобы встроить функцию в C, вы дополнительно должны явно указать компилятору, в какой файл .o следует поместить одно определение, на случай, если компилятор либо не сможет, либо не захочет встроить функцию через внешний встроенный.
Например, в ровно одном .c файле вы должны объявить такую функцию:
// util.c extern inline int max_int( int, int );
Это говорит компилятору «поместить одно определение для max_int() в util.o».
В качестве альтернативы в C вы также можете объявить встроенную функцию статической:
static inline int max_int( int a, int b ) { return a > b ? a : b; }
Если вы сделаете это, то:
Встроенные функции при разумном использовании могут повысить производительность. Как правило, только очень маленькие функции являются хорошими кандидатами для встраивания.
Начиная с C 11, встроенные функции можно альтернативно объявлять constexpr, но это уже история в другой раз.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3