C および C++ のインライン関数

PHPz
リリース: 2024-09-09 10:33:46
オリジナル
897 人が閲覧しました

Inline Functions in C and C++

導入

C++ では、関数定義にプレフィックスを付けることができる次のような inline キーワードが追加されました。

inline int max_int( int a, int b ) {
    return a > b ? a : b;
}
ログイン後にコピー

関数をインライン化することでプログラム全体のパフォーマンスが向上する可能性があるという「ヒント」をコンパイラに提供します。

インライン化された関数は、次の通常の関数呼び出しメカニズムを実行するのではなく、呼び出されるすべての時点でコードが展開されています。

  • レジスタを保存しています。
  • 引数値をスタックにプッシュします。
  • 呼び出し命令を実行します。
  • 最終的に ret 命令を実行する関数。
  • レジスタを復元しています。

非常に小さい関数の場合、インライン化によりパフォーマンスが向上する可能性があります。 しかし、他のほとんどすべてのものと同様に、トレードオフがあります。

inline キーワードは C99 にバックポートされましたが、要件が若干異なりました。詳細は後ほど説明します。

マクロとの違い

インライン関数は、関数のようなマクロに似ています (また、関数のようなマクロの多くの用途を置き換えることを目的としています)。 インライン関数関数であり、C も C++ も理解できないプリプロセッサによって行われる単なるテキスト置換ではなく、完全な関数セマンティクスを備えているため、これは一般に良いことです。

max_int() 関数と単純に等価なマクロ:

#define MAX_INT(A,B)  A > B ? A : B  /* bad implementation */
ログイン後にコピー

には次の問題があります:

  • MAX(n & 0xFF, 8) などの拡張された引数は、演算子の優先順位が間違っている可能性があります。
  • 副作用のある引数、たとえば MAX(n++, 8) には複数の副作用がある可能性があります。
  • 定義時に引数の型チェックは行われません。
  • エラーは多くの場合冗長で読みにくいです。

さらに、マクロ:

  • その引数を変更できます (これは、多くの場合、必要なものではありません)。

インライン関数にはこれらの問題はなく、同様のパフォーマンス上の利点が得られます。 したがって、関数のようなマクロではなく、インライン関数を使用してください。

ヒントだけ

前述したように、inline の指定は、関数がインライン化されることでプログラム全体のパフォーマンスが向上する可能性があるというコンパイラーへの「ヒント」にすぎません。 コンパイラはヒントを自由に無視できます。

なぜですか? それは良いアイデアではない、または不可能な場合があるからです。 次のいずれかが true の場合、関数はインライン化されないか、通常はインライン化されません。

  • 関数が「大きすぎます。」
  • 関数へのポインターを介して関数を呼び出します。
  • 関数は再帰的です。
  • 関数にはループがあります。

他の理由がある可能性があります。それはすべて、関数、その引数、コンパイラ、およびそれに与えられるオプションに大きく依存します。

コンパイラが関数をインライン化できない、またはインライン化しないことを選択した場合、(デフォルトでは) インライン化していないことを警告することはありません。 gcc などの一部のコンパイラには、警告を発し、関数がインライン化されなかった理由を示す -Winline オプションがあります。

inline の指定は、register を指定する古いコードに似ています。どちらも単なるヒントです。

インライン化する場合としない場合

ほとんどの関数では、関数の実行コストの大部分は関数呼び出しメカニズムではなく、関数の本体に発生します。 したがって、関数がインライン化の適切な候補であるためには、一般に次のようにする必要があります:

  • 十分に小さいため、関数呼び出しメカニズムのコストがほとんどを占めます。
  • タイトなループなど、パフォーマンスが実際に重要な場所で使用されます。

疑問がある場合は、コードのプロファイリングを行ってください。 インラインの使用は、「速くする」という魔法のキーワードではありません。 さらに、インラインを過度に使用すると、コードが肥大化し、プログラム全体のパフォーマンスが悪化する可能性があります。

詳細については、「インライン疾患」を参照してください。

インライン化の候補となることが多い関数は次のとおりです。

  • 「ゲッター」や「セッター」などの「ワンライナー」
  • 引数に特定の値を指定したり、キャストを行ったりする他の関数の呼び出しを囲む単純なラッパー。

理想的なインライン関数はパフォーマンスを向上させ、かつコード サイズを削減します。

ただし、インライン関数の定義が変更されると、それを使用するすべてのコードを再コンパイルする必要があるという点に注意してください。

インライン最適化

インライン関数が実際にコンパイラによってインライン展開される場合、通常の関数呼び出しメカニズムのコードを省略することに加えて、コンパイラは次のことも行うことができます。

  • Eliminate one or more function arguments completely whose values are constants via immediate addressing.
  • Perform better optimizations spanning the code the function is inlined into that it normally couldn’t perform across function boundaries.

Inline Function Definition

In order for the compiler to be able to inline a function, it has to be able to “see” its definition (not just its declaration) in every .c or .cpp file it’s used in just like a macro. Hence, an inline function must be defined in a header file.

Normally, a function, like everything else, must have exactly one definition by adhering to the one definition rule (ODR). However, since the definition of an inline function is “seen” in multiple .c or .cpp files, the ODR is suspended for that function.

It is possible to have different definitions for inline functions having the same name, but this results in undefined behavior since the compiler has no way to check that every definition is the same.

To inline a function in C++, all you need do is prefix the function definition with inline — that’s it. The compiler and/or linker will automatically discard all but one definition from the final executable file for you.

However, to inline a function in C, you additionally must explicitly tell the compiler into what .o file to put the one definition in the event the compiler is either unable or unwilling to inline a function via extern inline.

For example, in exactly one .c file, you would declare a function like:

// util.c
extern inline int max_int( int, int );
ログイン後にコピー

That tells the compiler to “put the one definition for max_int() into util.o.”

Alternatively in C, you can instead declare an inline function static also:

static inline int max_int( int a, int b ) {
    return a > b ? a : b;
}
ログイン後にコピー

If you do this, then:

  • You do not have to declare a function extern inline anywhere.
  • However, if the compiler doesn’t inline a function, it will generate a definition in every .c file it’s included into again leading to code bloat.
  • If the function has any static local variables, every definition will have distinct copies (that may or may not be what you want).

Conclusion

Inline functions, if used judiciously, can yield performance gains. Generally, only very small functions are good candidates for inlining.

Starting in C++11, inline functions can alternatively be declared constexpr, but that’s a story for another time.

References

  • Linux kernel coding style, §15 The inline disease.
  • Myth and reality about inline in C99.
  • The Annotated C++ Reference Manual, Margaret A. Ellis & Bjarne Stroustrup, Addison-Wesley, 1990, ISBN 0-201-51459-1, §7.1.2 Function Specifiers, pp. 99–105.

以上がC および C++ のインライン関数の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!