26

関数の前に inline キーワードを使用することと、ヘッダーで関数全体を宣言することの違いは何ですか?

それで...

int whatever() { return 4; }

.h:

inline int whatever();

.cpp:

inline int myClass::whatever()
{
    return 4;
}

さらに言えば、これは何をしますか:

inline int whatever() { return 4; }
4

5 に答える 5

29

いくつかの側面があります。

言語

  • 関数がinlineキーワードでマークされている場合、その定義は TU で使用可能である必要があります。そうでない場合、プログラムの形式が正しくありません。
  • クラス定義で定義されたすべての関数は、暗黙的にマークされinlineます。
  • (暗黙的または明示的に)マークされた関数はinline、(ODR を考慮して) 複数の TU で定義される場合がありますが、通常の関数の場合はそうではありません。
  • テンプレート関数 (完全に特殊化されていない) は、テンプレート関数と同じように扱われinlineます。

コンパイラの動作

  • マークされた関数inlineは、必要に応じて各オブジェクト ファイルの弱いシンボルとして発行されます。これにより、サイズが大きくなる可能性があります (テンプレートの肥大化を調べてください)。
  • コンパイラが実際に呼び出しをインライン化する (つまり、通常の関数呼び出しを実行する代わりに、使用時にコードをコピー/貼り付けする) のは、完全にコンパイラの裁量です。キーワードの存在は決定に影響する場合としない場合がありますが、せいぜいヒントにすぎません。

リンカーの動作

  • 弱いシンボルはマージされて、最終的なライブラリに 1 つ出現します。優れたリンカーは、複数の定義が一致していることを確認できますが、これは必須ではありません。
于 2012-04-11T09:51:45.787 に答える
10

の目的はinline、関数を複数の翻訳単位で定義できるようにすることです。これは、一部のコンパイラが関数が使用される場所にインライン化できるようにするために必要です。テンプレートやクラス定義内の関数を定義するときは省略できますが、ヘッダー ファイルで関数を定義するときは常に使用する必要があります。

ヘッダーなしで定義するのinlineは非常に悪い考えです。複数の翻訳単位のヘッダーを含めると、1 つの定義ルールが破られます。あなたのコードはおそらくリンクせず、リンクした場合に未定義の動作を示す可能性があります。

ヘッダーで宣言するinlineが、ソースファイルで定義することも非常に悪い考えです。定義は、それを使用するすべての翻訳単位で使用できる必要がありますが、ソース ファイルで定義することにより、1 つの翻訳単位でのみ使用できます。別のソース ファイルにヘッダーが含まれていて関数を呼び出そうとすると、プログラムは無効になります。

于 2012-04-11T10:34:29.543 に答える
10

がないと 、関数が名前空間またはグローバル スコープで宣言されている場合に、inline複数のエクスポートされたシンボルが作成される可能性があります(リンカー エラーが発生します)。

ただし、クラスの場合(例に見られるように)、ほとんどのコンパイラは暗黙的にメソッドをインラインとして宣言します(-fno-default-inlineGCCでそのデフォルトを無効にします)。

関数をインラインとして宣言すると、コンパイラはその定義を翻訳で確認することを期待する場合があります。したがって、定義が表示される時間のために予約する必要があります。

より高いレベル: クラス宣言の定義は、多くの場合、より多くの翻訳に表示されます。これにより最適化が向上し、コンパイル時間が長くなる可能性があります。

手作業による最適化と高速コンパイルの両方が重要でない限り、最近ではクラス宣言でキーワードを使用することは珍しくありません。

于 2012-04-11T09:25:32.713 に答える
3

この質問は、インライン関数について多くを説明しています __inline__ とはどういう意味ですか? (インラインキーワードについてでしたが。)

基本的にヘッダーとは関係ありません。ヘッダーで関数全体を宣言すると、関数のソースが含まれるソース ファイルが変更されるだけです。インライン キーワードは、結果としてコンパイルされた関数が配置される場所を変更します。すべての呼び出しの (パフォーマンスの向上)。ただし、コンパイラは、インラインにする関数またはメソッドを自分で選択する場合があり、キーワードは単にコンパイラへの提案です。インラインで指定されていない関数でも、パフォーマンスが向上する場合は、インラインになるようにコンパイラによって選択できます。

于 2012-04-11T09:26:54.073 に答える
1

複数のオブジェクトを実行可能ファイルにリンクしている場合、通常、関数の定義を含むオブジェクトは 1 つだけです。For int whatever() { return 4; }- オブジェクトを生成するために使用される翻訳単位には、関数の定義 (実行可能コード) が含まれwhateverます。リンカーは、呼び出し元をどちらに転送するかを知りません。が指定されている場合inline、実行可能コードは呼び出しサイトでインライン化される場合とされない場合がありますが、インライン化されていない場合、リンカはすべての定義が同じであると想定し、任意に 1 つを選択して呼び出し元を誘導することができます。どういうわけか定義が同じでない場合、それはあなたのせいと見なされ、未定義の動作が発生します。使用するにはinline、呼び出しをコンパイルするときに定義を知る必要があるため、インライン宣言をヘッダーに入れ、インライン定義を.cppファイルに入れるという考えは、すべての呼び出し元がたまたま同じ.cppファイルの後半にある場合にのみ機能します。一般的には壊れており、(名目上) インライン関数の定義が、それを宣言するヘッダーに表示されることを期待します (または、事前に宣言されていない単一の定義があることを期待します)。

于 2012-04-11T09:28:57.340 に答える