18

C++ では、キーワード "inline" は 2 つの目的を果たします。まず、定義を複数の翻訳単位に表示できます。2 つ目は、コンパイルされたコードで関数をインライン化する必要があるというコンパイラへのヒントです。

私の質問: GCC と Clang/LLVM によって生成されたコードでは、キーワード「インライン」は関数がインライン化されているかどうかに関係がありますか? はいの場合、どのような状況で?それとも、ヒントは完全に無視されますか? これは言語に関する質問ではなく、コンパイラ固有の質問であることに注意してください。

4

4 に答える 4

10

[注意: C++/GCC の第一人者ではありません] inline hereを読みたいと思うでしょう。

また、これは GCC/C99 用です。

インライン関数指定子を使用して行われた提案が有効である範囲 (C99 6.7.4)。

  • -fno-inline オプションが使用されている場合、または -O0 が使用されている場合、GCC は関数をインライン化しません。そうしないと、GCC は多くの理由で関数をインライン化できない可能性があります。-Winline オプションを使用して、関数がインライン化されていないかどうか、およびその理由を判断できます。

したがって、コンパイラの設定 (-fno-inlineまたはなど-O0) が使用されない限り、コンパイラはヒントを取得するようです。Clang/LLVM (または実際には GCC) についてコメントすることはできません。

-Winlineこれがコードゴルフの質問ではなく、何が起こっているのかを知る必要がある場合は、使用することをお勧めします.

于 2011-03-07T18:56:19.403 に答える
7

gccからの興味深い説明:インライン関数はマクロと同じくらい高速です:

一部の呼び出しは、さまざまな理由で統合できません(特に、関数の定義の前にある呼び出しは統合できず、定義内の再帰呼び出しも統合できません)。統合されていない呼び出しがある場合、関数は通常どおりアセンブラコードにコンパイルされます。プログラムがそのアドレスを参照する場合も、インライン化できないため、関数は通常どおりにコンパイルする必要があります。

関数定義での特定の使用法により、インライン置換に適さなくなる可能性があることに注意してください。これらの使用法には、varargsの使用、allocaの使用、可変サイズのデータ​​型の使用(Variable Lengthを参照)、計算されたgotoの使用(値としてのラベルを参照)、非ローカルgotoの使用、および入れ子関数(入れ子関数を参照)があります。-Winlineを使用すると、インラインとマークされた関数を置き換えることができなかった場合に警告が表示され、失敗の理由が示されます。

ISO C ++で要求されているように、GCCは、クラスの本体内で定義されたメンバー関数が、inlineキーワードで明示的に宣言されていない場合でも、インラインとしてマークされていると見なします。これは-fno-default-inlineでオーバーライドできます。C++ダイアレクトを制御するオプションを参照してください。

次のように、関数に `always_inline'属性を指定しない限り、GCCは最適化しないときに関数をインライン化しません。

 /* Prototype.  */
 inline void foo (const char) __attribute__((always_inline)); The remainder of this section is specific

GNUC90インライン化に。

インライン関数が静的でない場合、コンパイラは他のソースファイルからの呼び出しがある可能性があると想定する必要があります。グローバルシンボルはどのプログラムでも一度しか定義できないため、他のソースファイルで関数を定義してはならず、その中の呼び出しを統合することはできません。したがって、非静的インライン関数は常に通常の方法でそれ自体でコンパイルされます。

関数定義でinlineとexternの両方を指定すると、定義はインライン化にのみ使用されます。アドレスを明示的に参照している場合でも、関数が単独でコンパイルされることはありません。このようなアドレスは、関数を宣言しただけで定義しなかったかのように、外部参照になります。

インラインと外部のこの組み合わせは、ほとんどマクロの効果があります。これを使用する方法は、これらのキーワードを使用して関数定義をヘッダーファイルに配置し、定義の別のコピー(inlineとexternがない)をライブラリファイルに配置することです。ヘッダーファイルの定義により、関数へのほとんどの呼び出しがインライン化されます。関数の使用が残っている場合は、ライブラリ内の単一のコピーを参照します。

于 2011-03-07T19:30:48.817 に答える
5

GCC と LLVM プロジェクトのコードを読むことで、これに関する多くの情報を収集できます。コードを直接読んで収集した情報を次に示します。(注: これは必ずしも完全に包括的ではなく、inlineインライン化に影響を与えるすべての詳細をすべてリストしているわけではありません。ほとんどの概要を説明するだけです)

この情報は、2021/11/13 時点で GCC および LLVM の現在の開発 HEAD から収集されたものであるため、将来的に最新ではない可能性があります。

GCC 側:

LLVM 側:

言い換えれば、GCC と Clang の両方で、これは非常に強力なヒントのようです。

于 2021-11-13T17:23:35.553 に答える
4

ヒントの強度は、使用するコンパイル オプションに完全に依存します。ほとんどのコンパイラには、インライン化を行わないか、「インライン」とマークされたものだけをインライン化するか、最善の判断を下してヒントを無視するオプションがあります。

最後のものがおそらく最もうまく機能します。:-)

于 2011-03-07T19:05:13.727 に答える