inline, __inline, __forceinline

Спецификаторы inline и __inline предписывает компилятору вставить копию тела функции в каждое место, где в котором эта функция вызывается.

inline function_declarator;   
__inline function_declarator;   // Microsoft Specific
__forceinline function_declarator;   // Microsoft Specific

Заметки

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

Ключевое слово __forceinline отключает анализ затрат и выгод; в этом случае преимущество имеет мнение программиста. При использовании ключевого слова __forceinline необходимо проявлять осмотрительность. Постоянное использование ключевого слова __forceinline может привести к увеличению кода с минимальным приростом производительности, а в некоторых случаях даже с падением производительности (например, поскольку большой исполняемый файл требует более активного использования подкачки).

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

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

Ключевое слово inline доступно только в C++. Ключевые слова __inline и __forceinline доступны как в C, так и в C++. Для обеспечения совместимости с предыдущими версиями ключевые слова _inline и __inline являются синонимами.

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

  • Рекурсивные функции.

  • Функции, на которые создаются ссылки посредством указателя в любом месте блока трансляции.

Эти причины, наряду с некоторыми другими, могут препятствовать подстановке; конечное решение принимает компилятор. Программисту не следует полагаться на то, что использование ключевого слова inline вызовет подстановку функции.

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

Параметр оптимизации компилятора /Ob позволяет определить, выполнена ли подстановка.

Параметр /LTCG выполняет межмодульную подстановку вне зависимости от того, была ли она запрошена в исходном коде.

Пример 1

// inline_keyword1.cpp
// compile with: /c
inline int max( int a , int b ) {
   if( a > b ) 
      return a;
   return b;
}

Функции-члены класса могут быть объявлены как подставляемые либо при помощи ключевого слова inline, либо путем вставки определения функции в определение класса.

Пример 2

// inline_keyword2.cpp
// compile with: /EHsc /c
#include <iostream>
using namespace std;

class MyClass {
public:
   void print() { cout << i << ' '; }   // Implicitly inline
private:
   int i;
};

Блок, относящийся только к системам Microsoft

Ключевые слова __inline и inline эквивалентны.

Даже если используется ключевое слово __forceinline, компилятор не может выполнять подстановку кода во всех ситуациях. Компилятор не выполняет подстановку, если:

  • Функция или вызывающий ее объект скомпилированы с параметром /Ob0 (параметр по умолчанию для отладочной сборки).

  • В функции и вызывающем объекте используются разные типы (в одном — обработка исключений C++, а в другом — структурированная).

  • Функция имеет переменное число аргументов.

  • В функции используется встроенный код ассемблера (кроме случаев компиляции с параметром /Og, /Ox, /O1 или /O2).

  • Функция является рекурсивной и не сопровождается директивой #pragma inline_recursion(on). С помощью этой директивы выполняется подстановка рекурсивных функций с глубиной по умолчанию, 16 вызовам. Чтобы уменьшить глубину подстановки, используйте директиву #pragma inline_depth.

  • Функция является виртуальной, и для нее используется виртуальный вызов. Прямые вызовы виртуальных функций могут подставляться.

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

  • Функция также помечена модификатором naked __declspec.

Если компилятор не может выполнить подстановку функции, объявленной с ключевым словом __forceinline, он создает предупреждение уровня 1.

Рекурсивные функции можно подставляться до глубины, заданной директивой # pragma inline_depth, но не более 16 вызовов. Начиная с этой глубины рекурсивные функции обрабатываются как вызовы на экземпляр функции. Глубина, до которой эвристический поиск для подстановки функций проверяет рекурсивные функции, не может превышать 16 вызовов. Директива #pragma inline_recursion контролирует подстановку функции, которая расширяется в данный момент. Дополнительные сведения см. в разделе Расширение подставляемых функций, посвященный параметру компиляции /Ob.

Завершение блока, относящегося только к системам Microsoft

Дополнительные сведения об использовании спецификатора inline см. в следующих разделах:

См. также

Ссылки

Ключевые слова в C++

noinline

auto_inline