最初のヘッダー ファイルは、ret
それを含むすべての翻訳単位の外部リンケージで呼び出される関数を定義します。このような TU が同じプログラムで複数リンクされている場合、これは正しくありません。
2 番目のヘッダー ファイルは、ret
それを含むすべての翻訳単位の内部リンケージで呼び出される関数を定義します。これは、いくつがリンクされていても、各 TU が関数の独自のプライベート コピー (異なるアドレスを持つ) を持つことを意味します。
ヘッダー ファイルを使用してコードを共有するには、次の 3 つの正しい方法があります。
- 内部リンケージを持つ関数 (2 番目のヘッダー、または名前のない名前空間に配置することによる C++11 のように)。
static
外部リンケージを持つインライン関数 ( に置き換えinline
ます)。の意味はinline
、プログラム内に関数のコピーが 1 つしかないにもかかわらず、その関数を使用するすべての TU にその定義が含まれているということです。
- ヘッダーで関数を宣言し、その中で正確に 1 つの .cpp ファイル (たとえば ret.cpp) を定義します。
C++03 には 4 番目の方法がありました。
これは C++11 でも利用できると思いますが、C++11 では名前のない名前空間の関数はデフォルトで内部リンケージを持っています。名前のない名前空間の関数に外部リンケージを持たせるための C++11 の使用については知りません。したがって、関数に関する限り、名前のない名前空間は、関数に内部リンケージを与える良い方法です。
どちらを使用するかは、ニーズによって異なります。3 番目のオプションは、呼び出しコードを再コンパイルせずに関数の定義を変更できることを意味しますが、関数が dll にない限り、実行可能ファイルを再リンクする必要があります。
最初の 2 つ (static
またはinline
) は、次の場合に動作が異なります。
- 関数には
static
ローカル変数が含まれています。
- 関数ポインターを
ret
異なる TU で取得したものと比較し、
- 実行可能ファイルのサイズまたはシンボル テーブルを調べます。
- 関数の定義は TU ごとに異なります (おそらく #defines が異なるため)。これは、関数に外部リンケージがある場合は禁止されていますが、内部リンケージがある場合は禁止されていません。
それ以外はほとんど同じです。
標準によれば、inline
は、高速実行のためにコンパイラがその関数への呼び出しを最適化する必要があるというヒントでもあります (実際には、呼び出しサイトでコードをインライン化することを意味します)。ほとんどのコンパイラは、ほとんどの場合、このヒントを無視します。インライン化の良い候補であると評価した場合、static
しかし関数ではない関数を喜んでインライン化し、インライン化の悪い候補であると評価した場合、喜んで関数のインライン化を回避します。inline
inline