クラスのヘッダーファイル内でC++関数を定義すると関数がインラインになることを知りました。しかし、関数の隣にインライン・キーワードを置くことは単なる示唆に過ぎず、コンパイラは必ずしもそれに従わないことを知っています。これはヘッダーで定義されたC++関数と同じですか?また、スタンドアロンのC++関数とクラスの一部であるC++関数間の動作に違いがありますか?ヘッダー内に関数を定義すると、コンパイラーは常にインラインと見なしますか?
答えて
真実ではない
「クラスのヘッダファイル内のC++関数を定義するには、関数をインラインを作ります」。クラス定義の中で関数を定義する(つまり、宣言の代わりに関数の本体を提供する)ことはインラインにします。 「インラインにする」とは、インラインキーワードを与えることと同じ意味です。しかし、クラス定義はヘッダーにある必要はなく、ヘッダーにはクラス定義以外のものも含めることができます。
この例では、関数foo
は暗黙的にインラインです。 bar
が暗黙のうちに、インラインではありません機能:
struct Foo {
void foo() {}
void bar();
};
void Foo::bar() {}
inline
は二つの効果を持っている「機能の隣にinlineキーワードを入れては文句を言わない、必ずしもそれに従うだけの提案およびコンパイラです」。そのうちの1つは、無視できるコンパイラに対するヒントです。もう一方はオプションではなく、常にその効果があります。 「ヒント」は、コンパイラがその関数への呼び出しを関数自体のコードのコピーに置き換えることを推奨していることです。
複数の翻訳単位でインライン関数を定義でき、複数の定義エラーを伴わずにリンクされ、リンカーによってコピーの1つを除くすべてが削除されます。したがって、上記の例が複数の翻訳単位で共有されるヘッダーファイルに表示される場合は、bar
を明示的にインラインでマークする必要があります。そうしないと、リンカーはbar
の複数の定義を検出しますが、これは許可されていません。
名前にもかかわらず、C++のinline
はほとんどの場合、第2の強制的な効果であり、第1のオプションのものではありません。現代の最適化コンパイラは、どの呼び出しがインライン化されるべきかについて独自のアイデアを持っており、その決定を下すときにはinline
に多くの注意を払っていません。例えば、私は中程度の最適化レベルではgccに影響があると見てきましたが、低レベルでは何もインライン化されておらず、高レベルでは関数を作らない限り(呼び出しがコンパイルされたときに定義が利用可能な場合)大きすぎる。
関数がヘッダーまたはcppファイルで定義されているかどうかは、単独では何も影響しません。 #includeが行うことは、コンパイラがそれを見る前に、ヘッダファイルをコピーしてプリプロセッサのcppファイルに貼り付けることです。同じ変換単位で関数が呼び出されたときに関数が定義されている場合、その関数コードはコンパイラーによってインライン化されます。それらが異なる翻訳単位にある場合、コードは利用できず、コールはリンカーによってインライン化され、プログラム全体の最適化または同様のものでしかない。多分、「翻訳単位」とは、「すべてのヘッダーがコピーされて貼り付けられた後のcppファイル」を意味します。
C++コンパイラは、どのようなヒントを与えてもインラインになるものとできないものを自由に選択できます。関数がクラスの一部であるかどうか、またはそれがヘッダファイルかソースファイルのどちらにあるかは重要ではありません。コンパイラはその決定を下す際にそれらの事柄に注意を払わない。
正確には、コンパイラは、定義されていない関数をインライン化することはできません。これは、関数がインクルードされたヘッダーで宣言されていて、別のコンパイル単位で定義されている場合です。ただし、そのような最適化をサポートしている場合、リンカは関数をインライン展開することもできます。 –
@Carl:本当ですが、質問は反対の条件についてでした。私の答えはもう少し慎重に語られているはずです。 –
フリーのテンプレート以外の関数の定義をヘッダーファイルに配置すると、ヘッダーを含む各.cppファイルの関数定義が(直接的または間接的に)終了します。これはリンク時に問題を引き起こす可能性があります。
ただし、関数をインラインに宣言すると、リンカーは複数の場所に含まれていても1つの定義のみを使用します。
いいえ、必ずしもそうではありません。コンパイラはinline
キーワードのようにヒントとして扱いますが、コストやメリットがどのようなものかよく分かっているので、ほとんどは独自に決定します。コードをインライン化すると、関数呼び出しのオーバーヘッドは回避されますが、コードが大きくなり、命令キャッシュに悪影響を与えます。
これらのパフォーマンスヒントは、コンパイラによって一般的に無視されることが多くなりました。何も無視しない(またはむしろリンカが無視しない)ことは、inline
と宣言された関数がいくつかのコンパイル単位に現れることがあり、リンカエラーを引き起こすことなく同じ関数の複数のコピーとして扱われるべきです。
- 1. インライン関数を再定義するとどうなりますか?
- 2. コンパイラが独自の機能でインライン関数をインライン化できるのであれば、インライン関数をヘッダーに "定義"する必要があります
- 3. ヘッダーファイルに非インライン関数が定義されているとリンカーエラー?
- 4. ヘッダーとソースファイル関数の定義
- 5. テンプレートクラス定義の下でインライン関数を定義する
- 6. インライン関数を呼び出すときの未定義参照
- 7. インライン関数の定義が異なると、定義されていない動作ですか?
- 8. テンプレートリテラル内に関数を定義する
- 9. C++ヘッダー専用ライブラリのインライン関数とテンプレート関数
- 10. 関数内でnullデータを未定義として設定しますか?
- 11. 関数を使用するときに未定義になる
- 12. jQuery/Javascript:関数内にグローバル変数を定義するには?
- 13. 反応では、関数を定義しますが、定義されていないように見えます。
- 14. インライン関数「未定義シンボル」エラー
- 15. Cのインライン関数と "未定義の外部"エラー
- 16. ヘッダファイルに定義された小さな関数:インラインまたは静的?
- 17. 関数内で変数とエコーを定義する
- 18. はpopModal jQueryライブラリのHTML内の関数を定義しようとすると
- 19. PowerShellは関数内のオブジェクトを定義しますか?
- 20. 静的メンバー関数は暗黙的にインライン化されたクラス内で定義されていますか?
- 21. JavaScript - 関数内にあるときに 'this'ポインタが未定義になる
- 22. Libtool/clang:リンカーではなくコンパイラーに引数を渡します
- 23. インライン定義と宣言
- 24. 関数定義とクラス定義の違いは何ですか
- 25. 変数はjquery関数内で未定義を返します
- 26. typescriptコンパイラーは@inline関数のオプションを持っていますか?
- 27. 定義関数を正常に関数に含めるにはどうすればいいですか?
- 28. Emacsに変数の定義を見させることはできますか?
- 29. 従属変数をコンパイラーで定義するコンパクトな方法はありますか?
- 30. C構造内で関数を定義することは可能ですか?
+1は 'inline'キーワードの2番目の効果に言及しています。 –