インライン関数 (C++)Inline Functions (C++)

クラス宣言の本体で定義される関数はインライン関数です。A function defined in the body of a class declaration is an inline function.

Example

次のクラス宣言では、Account コンストラクターがインライン関数です。In the following class declaration, the Account constructor is an inline function. メンバー関数は、 GetBalanceDeposit、およびWithdrawとして指定されていないインラインがインライン関数として実装することができます。The member functions GetBalance, Deposit, and Withdraw are not specified as inline but can be implemented as inline functions.

// Inline_Member_Functions.cpp
class Account
{
public:
    Account(double initial_balance) { balance = initial_balance; }
    double GetBalance();
    double Deposit( double Amount );
    double Withdraw( double Amount );
private:
    double balance;
};

inline double Account::GetBalance()
{
    return balance;
}

inline double Account::Deposit( double Amount )
{
    return ( balance += Amount );
}

inline double Account::Withdraw( double Amount )
{
    return ( balance -= Amount );
}
int main()
{
}

注意

せず、クラス宣言で宣言された関数、インラインキーワード。In the class declaration, the functions were declared without the inline keyword. インラインクラス宣言でキーワードを指定することができます。 結果は同じです。The inline keyword can be specified in the class declaration; the result is the same.

特定のインライン メンバー関数は、すべてのコンパイル単位で同じ方法で宣言する必要があります。A given inline member function must be declared the same way in every compilation unit. この制約により、インライン関数は、インスタンス化された関数のように動作します。This constraint causes inline functions to behave as if they were instantiated functions. また、インライン関数の定義は正確に 1 つだけあることが必要です。Additionally, there must be exactly one definition of an inline function.

その関数の定義が含まれていない場合、クラス メンバー関数の外部リンケージを既定値、インライン指定子。A class member function defaults to external linkage unless a definition for that function contains the inline specifier. 前の例をこれらの関数必要がありますいない明示的に宣言すると、インライン指定子を使用してインライン関数の定義、インライン関数を使用すると、します。The preceding example shows that these functions need not be explicitly declared with the inline specifier; using inline in the function definition causes it to be an inline function. ただし、関数として再宣言するされていないインラインその関数を呼び出した後。However, it is illegal to redeclare a function as inline after a call to that function.

Inline、_ _inline、および__forceinlineInline, __inline, and __forceinline

インライン_ _inline指定子、関数が呼び出される適切な各場所に、関数本体のコピーを挿入するようコンパイラに指示します。The inline and __inline specifiers instruct the compiler to insert a copy of the function body into each place the function is called.

挿入 (インライン展開またはインライニングと呼ばれます) は、コンパイラの費用対効果分析により利益があるとわかった場合のみ発生します。The insertion (called inline expansion or inlining) occurs only if the compiler's cost/benefit analysis show it to be profitable. インライン展開では、関数呼び出しのオーバーヘッドが軽減されますが、コード サイズが大きくなるという潜在的なコストがあります。Inline expansion alleviates the function-call overhead at the potential cost of larger code size.

_ _Forceinlineキーワードは、費用対効果分析をオーバーライドし、代わりにプログラマの判断に依存しています。The __forceinline keyword overrides the cost/benefit analysis and relies on the judgment of the programmer instead. 使用する場合は注意 _ _forceinlineします。Exercise caution when using __forceinline. 区別しないで使用 _ _forceinlineマージナル パフォーマンスの向上だけで大規模なコードが発生したり、場合によっては、(ページングが増えるためより大きな実行可能ファイルなど) のパフォーマンスの低下もします。Indiscriminate use of __forceinline can result in larger code with only marginal performance gains or, in some cases, even performance losses (due to increased paging of a larger executable, for example).

インライン関数を使用すると、関数呼び出しに関連するオーバーヘッドが回避されるため、プログラムを高速化できます。Using inline functions can make your program faster because they eliminate the overhead associated with function calls. インライン展開される関数は、標準の関数では使用できない、コードの最適化の対象になります。Functions expanded inline are subject to code optimizations not available to normal functions.

インライン展開に関するオプションとキーワードは、インライン展開の対象となる候補をコンパイラに示すだけです。The compiler treats the inline expansion options and keywords as suggestions. 関数がインライン展開される保証はありません。There is no guarantee that functions will be inlined. 使用しても、特定の関数のインライン展開を強制することはできません、 _ _forceinlineキーワード。You cannot force the compiler to inline a particular function, even with the __forceinline keyword. コンパイルするときに /clrコンパイラはインラインではなく、関数、関数に適用されるセキュリティ属性がある場合。When compiling with /clr, the compiler will not inline a function if there are security attributes applied to the function.

インラインキーワードは C++ でのみ使用できます。The inline keyword is available only in C++. _ _Inline_ _forceinlineキーワードは C の両方で使用できるとC++します。The __inline and __forceinline keywords are available in both C and C++. 以前のバージョンとの互換性のため _inline_forceinlineのシノニムで _ _inline、および _ _forceinlineしない限り、コンパイラ オプション/Za(言語拡張機能を無効にする)を指定します。For compatibility with previous versions, _inline and _forceinline are synonyms for __inline, and __forceinline unless compiler option /Za (Disable language extensions) is specified.

インラインキーワードは、インライン展開が優先されることをコンパイラに指示します。The inline keyword tells the compiler that inline expansion is preferred. ただし、コンパイラは、コードをインラインで挿入する代わりに、関数の別のインスタンスを作成 (インスタンス化) し、標準の呼び出しリンケージを作成できます。However, the compiler can create a separate instance of the function (instantiate) and create standard calling linkages instead of inserting the code inline. このようになるのは、次の 2 つの場合です。Two cases where this can happen are:

  • 再帰関数。Recursive functions.

  • 翻訳単位の別の場所にあるポインターを通じて参照される関数。Functions that are referred to through a pointer elsewhere in the translation unit.

これらの理由を妨げる可能性、インライン展開may 他のユーザーと、;、コンパイラの裁量でする必要がありますに依存しない、インラインのためインライン化できません関数指定子。These reasons may interfere with inlining, as may others, at the discretion of the compiler; you should not depend on the inline specifier to cause a function to be inlined.

通常の関数の場合と同様に、インライン関数への引数の評価の順序は定義されていません。As with normal functions, there is no defined order of evaluation of the arguments to an inline function. 実際には、通常の関数呼び出しプロトコルで渡される引数の評価順序とは異なる場合があります。In fact, it could be different from the order in which the arguments are evaluated when passed using normal function call protocol.

/Obコンパイラ最適化オプションは、関数のインライン展開が実際に発生するかどうかを判断するのに役立ちます。The /Ob compiler optimization option helps to determine whether inline function expansion actually occurs.

/LTCGクロス モジュール ソース コードで要求されたかどうかにかかわらずインライン化を実行します。/LTCG performs cross-module inlining regardless of whether it was requested in source code.

例 1Example 1

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

クラスのメンバー関数を使用してインラインで宣言することができます、インラインキーワードまたはクラス定義内で関数の定義を配置することで。A class's member functions can be declared inline either by using the inline keyword or by placing the function definition within the class definition.

例 2Example 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 固有の仕様Microsoft Specific

_ _Inlineキーワードは等価インラインします。The __inline keyword is equivalent to inline.

使用しても _ _forceinlineコンパイラは、すべての環境でのインライン コードをことはできません。Even with __forceinline, the compiler cannot inline code in all circumstances. 次の場合、コンパイラは関数をインライン展開できません。The compiler cannot inline a function if:

  • 関数またはその呼び出し元が /Ob0 (デバッグ ビルドの既定オプション) でコンパイルされる。The function or its caller is compiled with /Ob0 (the default option for debug builds).

  • 関数と呼び出し元が、異なる種類の例外処理を使用する (一方は C++ 例外処理、他方は構造化例外処理)。The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other).

  • 関数に可変個引数リストが含まれている。The function has a variable argument list.

  • 関数が /Og、/Ox、/O1、または /O2 を指定してコンパイルされていない場合に、インライン アセンブリを使用する。The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.

  • 関数は再帰的なとが付属しない #pragma inline_recursionします。The function is recursive and not accompanied by #pragma inline_recursion(on). プラグマによって、再帰関数はインライン展開され、既定の深さは 16 呼び出しになります。With the pragma, recursive functions are inlined to a default depth of 16 calls. インラインの深度を減らすためには、次のように使用します。 inline_depthプラグマ。To reduce the inlining depth, use inline_depth pragma.

  • 関数が仮想で、仮想的に呼び出される。The function is virtual and is called virtually. 仮想関数への直接呼び出しはインライン展開できます。Direct calls to virtual functions can be inlined.

  • プログラムが関数のアドレスを受け取り、関数へのポインターによって呼び出される。The program takes the address of the function and the call is made via the pointer to the function. 受け取られるアドレスを持っている関数への直接呼び出しはインライン展開できます。Direct calls to functions that have had their address taken can be inlined.

  • 関数が付いたしても、 naked _ _declspec修飾子。The function is also marked with the naked __declspec modifier.

場合、コンパイラはインラインで宣言された関数 _ _forceinline、場合を除き、レベル 1 の警告が生成されます。If the compiler cannot inline a function declared with __forceinline, it generates a level 1 warning, except when:

  • /Od か、/Ob0 を使用して、関数がコンパイルされます。The function is compiled by using /Od or /Ob0. いいえインライン展開が、このような場合に必要です。No inlining is expected in these cases.

  • 関数は、含まれるライブラリまたは別の翻訳単位の外部で定義されているまたはが仮想呼び出しのターゲットまたは間接的な呼び出しのターゲット。The function is defined externally, in an included library or another translation unit, or is a virtual call target or indirect call target. コンパイラは、現在の翻訳単位内に見つからないことを示す非インライン コードを識別できません。The compiler can't identify non-inlined code that it can't find in the current translation unit.

再帰関数はインラインで置き換えるによって指定される深度を指定できます、 inline_depthプラグマを最大 16 の呼び出し。Recursive functions can be substituted inline to a depth specified by the inline_depth pragma, up to a maximum of 16 calls. その深さの後、再帰関数の呼び出しは、関数のインスタンスへの呼び出しとして扱われます。After that depth, recursive function calls are treated as calls to an instance of the function. 再帰関数がインライン ヒューリスティックによってチェックされる深さは、16 を超えることはできません。The depth to which recursive functions are examined by the inline heuristic cannot exceed 16. Inline_recursionプラグマは、現在展開中の関数のインライン展開を制御します。The inline_recursion pragma controls the inline expansion of a function currently under expansion. 参照してください、関数のインライン展開(/Ob) 関連情報については、コンパイラ オプション。See the Inline-Function Expansion (/Ob) compiler option for related information.

Microsoft 固有の仕様はここまでEND Microsoft Specific

使用しての詳細については、インライン指定子を参照してください。For more information on using the inline specifier, see:

インライン関数を使用する状況When to use inline functions

インライン関数は、プライベート データ メンバーにアクセスする関数のような小さな関数に使用するのが最適です。Inline functions are best used for small functions such as accessing private data members. これらの 1 行または 2 行の "アクセサー" 関数の主な目的は、オブジェクトに関する状態情報を返すことです。短い関数は、関数呼び出しのオーバーヘッドに敏感です。The main purpose of these one- or two-line "accessor" functions is to return state information about objects; short functions are sensitive to the overhead of function calls. 長い関数は、呼び出すシーケンスと返すシーケンスにかかる時間が相対的に少なく、インライン展開の利点が少なくなります。Longer functions spend proportionately less time in the calling/returning sequence and benefit less from inlining.

APointクラスは、次のように定義できます。A Point class can be defined as follows:

// when_to_use_inline_functions.cpp
class Point
{
public:
    // Define "accessor" functions as
    //  reference types.
    unsigned& x();
    unsigned& y();
private:
    unsigned _x;
    unsigned _y;
};

inline unsigned& Point::x()
{
    return _x;
}
inline unsigned& Point::y()
{
    return _y;
}
int main()
{
}

座標の操作がクライアントでこのようなクラスの 2 つのアクセサー関数を指定することは比較的一般的な操作を (xy前の例) としてインライン通常を保存します、上のオーバーヘッド。Assuming coordinate manipulation is a relatively common operation in a client of such a class, specifying the two accessor functions (x and y in the preceding example) as inline typically saves the overhead on:

  • 関数呼び出し (パラメーターの引き渡しおよびスタックへのオブジェクトのアドレスの配置を含む)Function calls (including parameter passing and placing the object's address on the stack)

  • 呼び出し元のスタック フレームの保持Preservation of caller's stack frame

  • 新しいスタック フレームのセットアップNew stack-frame setup

  • 戻り値のやり取りReturn-value communication

  • 元のスタック フレームの復元Old stack-frame restore

  • ReturnReturn

インライン関数とマクロの比較Inline functions vs. macros

インライン関数はマクロに似ていますが、インライン関数がコンパイラによって解析されるのに対し (関数コードはコンパイル時に呼び出しの時点で展開されるため)、マクロはプリプロセッサによって展開されます。Although inline functions are similar to macros (because the function code is expanded at the point of the call at compile time), inline functions are parsed by the compiler, whereas macros are expanded by the preprocessor. そのため、これらにはいくつかの重要な違いがあります。As a result, there are several important differences:

  • インライン関数は、通常の関数に適用されるタイプ セーフのすべてのプロトコルに従います。Inline functions follow all the protocols of type safety enforced on normal functions.

  • インライン関数を指定する点が異なりますとして他の関数と同じ構文を使用して、インライン関数の宣言でキーワード。Inline functions are specified using the same syntax as any other function except that they include the inline keyword in the function declaration.

  • インライン関数に引数として渡された式は、1 回だけ評価されます。Expressions passed as arguments to inline functions are evaluated once. マクロでは、引数として渡された式が複数回評価される可能性があります。In some cases, expressions passed as arguments to macros can be evaluated more than once.

次の例は、小文字を大文字に変換するマクロを示しています。The following example shows a macro that converts lowercase letters to uppercase:

// inline_functions_macro.c
#include <stdio.h>
#include <conio.h>

#define toupper(a) ((a) >= 'a' && ((a) <= 'z') ? ((a)-('a'-'A')):(a))

int main() {
   char ch;
   printf_s("Enter a character: ");
   ch = toupper( getc(stdin) );
   printf_s( "%c", ch );
}
//  Sample Input:  xyz
// Sample Output:  Z

式の目的は、toupper(getc(stdin))コンソール デバイスからの文字が読み取られるは (stdin) と、必要に応じてが大文字に変換します。The intent of the expression toupper(getc(stdin)) is that a character should be read from the console device (stdin) and, if necessary, converted to uppercase.

マクロの実装により、入力文字が "a" 以上であるかどうかを判断するため getc が 1 回実行され、さらにその文字が "z" 以下であるかどうかを判断するためもう 1 回実行されます。Because of the implementation of the macro, getc is executed once to determine whether the character is greater than or equal to "a," and once to determine whether it is less than or equal to "z." 入力文字がその範囲にある場合、getc が再実行されて、文字が大文字に変換されます。If it is in that range, getc is executed again to convert the character to uppercase. つまり、このプログラムでは文字を 2 回または 3 回にわたって待機しますが、待機は 1 回だけに抑えるのが本来最適な方法です。This means the program waits for two or three characters when, ideally, it should wait for only one.

インライン関数を使用すると、このような問題が解消されます。Inline functions remedy the problem previously described:

// inline_functions_inline.cpp
#include <stdio.h>
#include <conio.h>

inline char toupper( char a ) {
   return ((a >= 'a' && a <= 'z') ? a-('a'-'A') : a );
}

int main() {
   printf_s("Enter a character: ");
   char ch = toupper( getc(stdin) );
   printf_s( "%c", ch );
}
Sample Input: a
Sample Output: A

関連項目See also

noinlinenoinline
auto_inlineauto_inline