コンパイラはいつC ++コードをインライン化しますか?
-
22-07-2019 - |
質問
C ++では、メソッドが明示的に inline
で宣言されている(またはヘッダーファイルで定義されている)場合にのみインライン化されますか?
解決
はい、コンパイラは inline
として明示的に宣言されていなくてもコードをインライン化できます。
基本的に、セマンティクスが変更されていない限り、コンパイラーは生成されたコードに対して事実上何でもできます。この規格は、生成されたコードに対して特別なことを強制しません。
他のヒント
inline キーワードは、同じ関数の複数の同一の定義がエラーではないことを実際にリンカーに伝えます(またはコンパイラーにリンカーに伝えます)。ヘッダーで関数を定義したい場合、または「複数の定義」を取得する場合に必要です。ヘッダーが複数のコンパイル単位に含まれている場合、リンカーからのエラー。
キーワードとして inline を選択する理由は、(テンプレートではない)関数をヘッダーに定義する唯一の理由は、コンパイラによってインライン化できるためだと思われる。コンパイラは、完全な定義がない限り、関数呼び出しをインライン化できません。関数がヘッダーで定義されていない場合、コンパイラーは宣言のみを持ち、必要な場合でも関数をインライン化できません。
最近では、コードを最適化するのはコンパイラーだけではなく、リンカーもそれを行うことができると聞いています。リンカは、関数が同じコンパイル単位で定義されていなくても、インラインで関数呼び出しを行うことができます(まだ実行していない場合)。
そして、ヘッダー内の単一行よりも大きい関数を定義することは、おそらくあまり良い考えではありません(コンパイル時間に問題があり、大きな関数がインライン化されると、膨張してパフォーマンスが低下する可能性があります)。
コンパイラは、関数をインライン化する場合とインライン化しない場合があります。この決定のヒントとして inline
装飾を使用できますが、無視することもできます。
また、クラスメンバー関数は、クラス定義で直接定義されている場合、暗黙の inline
装飾があります。
コンパイラは、インライン宣言を無視する場合があります。これは基本的にコンパイラーがヒントとして使用して、そうするかどうかを決定します。コンパイラーは、インラインとマークされたものをインライン化する義務も、そうでないものもインライン化する義務を負いません。基本的に、あなたはあなたのコンパイラとあなたが選択した最適化レベルに翻弄されています。
私が間違っていない場合、最適化がオンになっていると、コンパイラは適切なルーチンまたはメソッドをインライン化します。
IBM インフォメーションセンター、
インライン指定子の使用は、 コンパイラーへの提案 インライン展開を実行できます。その コンパイラは自由に無視できます 提案。
C言語 mainを除くすべての関数を宣言または インラインとインラインとして定義 関数指定子。静的ローカル 変数は インラインの本体内で定義 関数。
クラス宣言の内部に実装されるC ++ 関数は 自動的に定義されたインライン。レギュラー C ++関数とメンバー関数 クラス外で宣言された 宣言を除く main、として宣言または定義できます インライン関数とインライン 指定子。静的ローカルと文字列 の本体内で定義されたリテラル インライン関数は 翻訳ユニット間で同じオブジェクト;
実装に依存するため、コンパイラのドキュメントで説明する必要があります。たとえば、GCCのマニュアルによると、GCCは最適化が適用されない限り、コードをインライン化しません。
コンパイラがコードをインライン化しない場合、 inline キーワードは static と同じ効果を持ち、コードを呼び出す各コンパイル単位には独自のコピーがあります。スマートリンカーは、これらを単一のコピーに減らすことができます。
インライン展開がコードのセマンティクスに違反せず、関数コードに到達できる場合、コンパイラは必要なものをインライン化できます。選択的にインライン化することもできます-良いアイデアだと感じたときはインライン化し、良いアイデアだと感じないときやコードのセマンティクスに違反するときはインライン化しません。
関数が別の翻訳単位にある場合でも、一部のコンパイラはインライン化できます。これはリンク時コード生成と呼ばれます。
インライン化がコードのセマンティクスに違反する典型的なケースは、仮想呼び出しであり、関数アドレスを別の関数に渡すか、保存します。
反対を指定しない限り、コンパイラは必要に応じて最適化します。
inlineキーワードは、コンパイラへの単なるリクエストです。コンパイラーは、関数をインライン化するかどうかを決定します。コンパイラの決定を左右する主な要因の1つは、コードの単純さです(ループは多くありません)
メンバー関数はデフォルトでインラインで宣言されます。(コンパイラもここで決定します)
これらは厳格なルールではありません。コンパイラの実装によって異なります。
関係する他の要因を知っている人がいれば、投稿してください。
インライン展開が機能しない状況の一部は次のとおりです。
- ループ、スイッチ、またはgotoが存在する場合、値を返す関数の場合
- 関数が値を返さない場合、return文が存在する場合;
- 関数に静的変数が含まれる場合
- インライン関数が再帰的である場合。
インライン展開は、関数呼び出しとreturnステートメントのオーバーヘッドがなくなるため、プログラムの実行を高速化します。ただし、インライン関数を定義するステートメントは関数が呼び出される各ポイントで再現されるため、プログラムがより多くのメモリを使用するようになります。そのため、トレードオフが必要になります。
(私のOOPブックの1つに記載)