1. ホーム
  2. c++

[解決済み】インライン関数を使用する場合と使用しない場合とは?

2022-04-05 05:09:48

質問

インラインはコンパイラへのヒントまたはリクエストであり、関数呼び出しのオーバーヘッドを回避するために使用されることは知っています。

では、ある関数がインライン化の候補であるかどうかは、何を基準に判断すればよいのでしょうか? どのような場合にインライン化を避けるべきでしょうか?

解決方法は?

関数呼び出しのコストを回避することは、物語の半分に過ぎません。

を行う。

  • 使用 inline の代わりに #define
  • 極小 の関数の良い候補です。 inline : コードが速く、実行ファイルが小さくなる (コードキャッシュに残る可能性が高くなる)
  • 機能が小さい そして 非常に頻繁に呼び出される

はしないでください。

  • 大きな関数:実行ファイルのサイズが大きくなり、呼び出しのオーバーヘッドによる実行の高速化にかかわらず、パフォーマンスが著しく低下します。
  • I/Oバインドされているインライン関数
  • この関数はあまり使用されません。
  • コンストラクタとデストラクタ:空の場合でも、コンパイラはそのためのコードを生成します。
  • ライブラリ開発時のバイナリ互換性の破壊
    • 既存の関数をインライン化する
    • インライン関数を変更、またはインライン関数を非インライン化:旧バージョンのライブラリは旧実装を呼び出す

ライブラリを開発する場合、将来的に拡張可能なクラスにするために、以下のような工夫が必要です。

  • ボディが空の場合でも、ノンインラインの仮想デストラクタを追加しました。
  • すべてのコンストラクタを非インライン化
  • クラスを値でコピーできない場合を除き、コピー コンストラクタと代入演算子の非インライン実装を記述します。

を覚えておいてください。 inline キーワードはコンパイラへのヒントです。コンパイラはある関数をインライン化しないことを決定することもあれば inline を使用します。私は一般に、関数 inline (非常に小さな関数を書く場合は別として)。

パフォーマンスについては、(いつものように)アプリケーションのプロファイルを作成し、最終的に inline ボトルネックとなる関数を抽出します。

参考文献


EDIT: Bjarne Stroustrup, The C++ Programming Language:

<ブロッククオート

関数は、以下のように定義することができます。 inline . 例えば

inline int fac(int n)
{
  return (n < 2) ? 1 : n * fac(n-1);
}

inline の呼び出しに対応するコードを生成するようにコンパイラに指示します。 fac() というのは、一旦関数のコードを書いてから通常の関数呼び出しメカニズムで呼び出すのではなく、インラインで呼び出すからです。賢いコンパイラは、定数 720 を呼び出した場合 fac(6) . 相互に再帰的なインライン関数や、入力によって再帰するインライン関数、しないインライン関数などがあり得るため、すべてのインライン関数の呼び出しを保証することは不可能です。 inline 関数は実際にインライン化されています。コンパイラの賢さの程度は法律で定めることができないので、あるコンパイラは 720 また、別の 6 * fac(5) そして、さらに別のインライン化されていない呼び出し fac(6) .

非常に巧妙なコンパイルやリンクの機能がない場合でもインライン化を可能にするために、インライン関数の定義(宣言だけでなく)がスコープ内になければなりません(9.2節)。例えば inline エスペシファイアは関数のセマンティクスに影響を与えません。特に、インライン関数は依然として一意なアドレスを持っており、そのため static 変数 (§7.1.2) を持つインライン関数です。

EDIT2: ISO-IEC 14882-1998, 7.1.2 関数指定子

関数宣言(8.3.5、9.3、11.4)に inline 指定子は、インライン関数を宣言します。インライン指定子は、通常の関数呼び出しメカニズムよりも、呼び出し時に関数本体をインラインで置換することを優先することを実装に示します。しかし,このインライン置換が省略されても,7.1.2 で定義されたインライン関数の他の規則は尊重されなければならない。