インライン関数とは、コンパイラーがメモリー内に独立した命令セットを 作成するのではなく、関数定義のコードを呼び出し側の関数のコードに直接コピーする関数のことです。 関数コード・セグメントとの間で制御権を移動するのではなく、変更された関数本体のコピーを関数呼び出しの 代わりに直接使用することができます。このようにして、関数呼び出しのパフォーマンス上の オーバーヘッドが回避されます。
inline 関数指定子を使用して、あるいはクラスまたは構造体定義 の中でメンバー関数を定義して、関数をインラインとして宣言します。 inline 指定子は、インライン展開が実行可能であることを コンパイラーに提案するものにすぎません。コンパイラーはこの提案を 無視してもかまいません。
以下のコードの断片では、インライン関数の定義を示しています。
inline int add(int i, int j) { return i + j; }
inline 指定子を使用しても、関数の意味は変わりません。 ただし、関数をインライン展開すると、実引き数の評価の順序が保たれなくなる場合があります。 また、インライン展開によって関数のリンケージが変更されることもありません。リンケージは デフォルトでは外部になっています。
C++ では、メンバー関数と非メンバー関数は、両方ともインラインにすることができます。
クラス宣言の本体内部にインプリメントされたメンバー関数は、
暗黙で inline を宣言されます。コンパイラーによって作成される
コンストラクター、コピー・コンストラクター、代入演算子、およびデストラクターも、暗黙で
inline を宣言
されます。コンパイラーがインラインに
しない inline 関数は、通常の関数と同じように処理されます。つまり、その関数が定義されている
変換単位の数に関係なく、関数のコピーは 1 つしか存在しません。
C では、内部結合を持つ関数はどの関数でもインラインにできますが、外部結合を持つ関数には制限が課せられています。
この制限は以下のとおりです。
C では、インライン定義は、対応する外部定義、および別の変換単位内の 別の対応するインライン定義とは異なっています。
言語拡張できるようにソース・コードをコンパイルした場合、インライン関数の振る舞いは GNU C の セマンティクスに従います。関数定義に extern inline が明示的に 指定されている場合は、コンパイラーはインライン化のためだけに extern inline 定義を使用します。 その場合の振る舞いはマクロ展開に似ています。ある関数の extern inline 定義がヘッダー・ファイルにある 場合、extern または inline が指定されていないその関数の外部定義を別のファイルから得るように しなければなりません。この定義は、ヘッダー・ファイルをインクルードしていないファイルからその関数を呼び出す場合に 使用されます。
次の例は、extern inline のセマンティクスを示したものです。 GNU セマンティクスでコンパイルされると、two() に対するインラインではない関数本体は生成されません。
inline.h: #include<stdio.h> extern inline void two(void){ // GNU C uses this definition only for inlining printf("From inline.h¥n"); } main.c: #include "inline.h" int main(void){ void (*pTwo)() = two; two(); (*pTwo)(); } two.c: #include<stdio.h> void two(){ printf("In two.c¥n"); }
以下の出力は、two への最初の関数呼び出しが実際にインラインにされた場合の結果を示したものです。
Using the gcc semantics for the inline keyword: From inline.h In two.c
コンパイラーは inline 関数指定子があっても、extern inline 関数 two をインラインにしない場合もあります。
関連参照