ヘッダーファイルに関数定義を追加するにはどうすればよいですか?
これは、次の3つの方法で実現できます。
- 関数のマーキング
inline
または
- 関数を作成する
static
か
- 関数を匿名の名前空間に配置します。
そうするための正しい方法は何ですか?
#1
つまり、関数にマークを付けることは、単一定義規則inline
に違反することなくこれを行う正しい方法です。
他の2つのアプローチの何が問題になっていますか?
両方#2
と#3
各変換ユニットには、独自のバージョンの関数が含まれ、プログラムにはいくつかの異なるバージョンの関数が含まれるため、生成されるバイナリのサイズが大きくなります。
つまり、static
関数の場合fun()
、&fun
は変換単位ごとに異なり、プログラムにN
は関数の異なるバージョンが含まれます。
また、関数に静的ローカル変数が含まれている場合は、N
関数インスタンスごとに1つずつ、異なる静的ローカル変数があります。
最初のアプローチでこの問題をどのように回避しますか?
関数には外部inline
リンケージがあります。
関数にマークを付けると、inline
その関数はすべての変換単位で同じアドレスを持ちます。また、インライン関数の本体内で定義された静的ローカルおよび文字列リテラルは、変換ユニット全体で同じオブジェクトとして扱われます。
つまり、インライン関数はすべての変換ユニットで同じアドレスを持ちます。
static inline
ヘッダーの関数定義はどのように扱われますか?
キーワードはstatic
、関数に内部リンケージを強制します。
インラインとして定義された関数の各インスタンスは個別の関数として扱われ、各インスタンスには静的ローカルと文字列リテラルの独自のコピーがあります。したがって、これはに似てい#2
ます。
注:
標準inline
では、ユーザープログラムの関数のすべての定義が、関数が使用または呼び出されるすべての変換単位でまったく同じ定義を持っている必要があります。
関連するスタンダーデスの参考文献:
C++03標準
3.2 1つの定義規則:
パラ3:
すべてのプログラムには、そのプログラムで使用されるすべての非インライン関数またはオブジェクトの定義が1つだけ含まれている必要があります。診断は必要ありません。定義は、プログラムに明示的に表示することも、標準またはユーザー定義のライブラリに含めることも、(適切な場合は)暗黙的に定義することもできます(12.1、12.4、および12.8を参照)。インライン関数は、それが使用されるすべての変換単位で定義されるものとします。
7.1.2関数指定子
パラ4:
インライン関数は、それが使用されるすべての変換単位で定義され、すべての場合でまったく同じ定義を持つ必要があります(3.2)。[注:インライン関数の呼び出しは、その定義が変換ユニットに表示される前に発生する可能性があります。]外部リンケージを持つ関数が1つの変換単位でインラインとして宣言されている場合、それが表示されるすべての変換単位でインラインで宣言されるものとします。診断は必要ありません。外部リンケージを持つインライン関数は、すべての変換ユニットで同じアドレスを持つ必要があります。anexternインライン関数の静的ローカル変数は、常に同じオブジェクトを参照します。externインライン関数の文字列リテラルは、異なる変換単位の同じオブジェクトです。