ここで何かが足りないと思います。
静的関数?
関数をstaticと宣言すると、コンパイルユニットで「非表示」になります。
名前空間スコープ(3.3.6)を持つ名前は、次の名前の場合、内部リンケージがあります。
—静的に明示的に宣言されている変数、関数、または関数テンプレート。
3.5 / 3-C ++ 14(n3797)
名前に内部リンケージがある場合、その名前が示すエンティティは、同じ変換単位内の他のスコープからの名前で参照できます。
3.5 / 2-C ++ 14(n3797)
この静的関数をヘッダーで宣言すると、このヘッダーを含むすべてのコンパイルユニットが独自の関数のコピーを持ちます。
その関数内に静的変数がある場合、このヘッダーを含む各コンパイルユニットにも独自の個人用バージョンがあります。
インライン関数?
インラインとして宣言すると、インライン化の候補になります(C ++では、コンパイラーがインライン化するかどうかにかかわらず、キーワードinlineが存在するか存在しないかを無視することがあるため、あまり意味がありません)。
インライン指定子を使用した関数宣言(8.3.5、9.3、11.3)は、インライン関数を宣言します。インライン指定子は、呼び出しポイントでの関数本体のインライン置換が通常の関数呼び出しメカニズムよりも優先されることを実装に示します。呼び出しの時点でこのインライン置換を実行するために実装は必要ありません。ただし、このインライン置換が省略されている場合でも、7.1.2で定義されているインライン関数の他の規則は尊重されます。
7.1.2 / 2-C ++ 14(n3797)
ヘッダーには、興味深い副作用があります。インライン関数は同じモジュールで複数回定義でき、リンカーは単に「それら」を1つに結合します(コンパイラーの理由でインライン化されていない場合)。
内部で宣言された静的変数の場合、標準では具体的に1つと記載されており、そのうちの1つだけです。
externインライン関数の静的ローカル変数は、常に同じオブジェクトを参照します。
7.1.2 / 4-C ++ 98 / C ++ 14(n3797)
(関数はデフォルトでexternであるため、関数を静的として明確にマークしない限り、これはその関数に適用されます)
これには、欠陥のない「静的」(つまり、ヘッダーで定義できる)という利点があります(インライン化されていない場合、最大で1回存在します)。
静的ローカル変数?
静的ローカル変数にはリンクがありません(スコープ外の名前で参照することはできません)が、静的ストレージ期間があります(つまり、グローバルですが、その構築と破棄は特定のルールに従います)。
静的+インライン?
インラインと静的を混合すると、説明した結果が得られます(関数がインライン化されている場合でも、内部の静的変数はインライン化されず、静的関数の定義を含むコンパイル単位と同じ数の静的変数で終了します。 )。
著者の追加の質問への回答
質問を書いたので、Visual Studio 2008で試してみました。VSが標準に準拠して動作するようにするすべてのオプションをオンにしようとしましたが、一部を見逃した可能性があります。結果は次のとおりです。
関数が単に「インライン」である場合、静的変数のコピーは1つだけです。
関数が「静的インライン」の場合、変換単位と同じ数のコピーがあります。
本当の問題は、物事がこのようになっているのか、それともこれがMicrosoft C ++コンパイラの特異性なのかということです。
だから私はあなたがそのようなものを持っていると思います:
void doSomething()
{
static int value ;
}
関数内の静的変数、簡単に言えば、関数のスコープ以外のすべてに隠されたグローバル変数、つまり、関数内で宣言された関数のみがそれに到達できることを理解する必要があります。
関数をインライン化しても何も変わりません。
inline void doSomething()
{
static int value ;
}
非表示のグローバル変数は1つだけです。コンパイラがコードをインライン化しようとするという事実は、グローバルな隠れた変数が1つしかないという事実を変えることはありません。
ここで、関数が静的であると宣言されている場合:
static void doSomething()
{
static int value ;
}
次に、コンパイル単位ごとに「プライベート」になります。つまり、静的関数が宣言されているヘッダーを含むすべてのCPPファイルには、グローバルな非表示変数の独自のプライベートコピーを含む、関数の独自のプライベートコピーがあります。ヘッダーを含むコンパイル単位があります。
内部に「static」変数を含む「static」関数に「inline」を追加します。
inline static void doSomething()
{
static int value ;
}
内部の静的変数に関する限り、この「インライン」キーワードを追加しない場合と同じ結果になります。
したがって、VC ++の動作は正しく、「インライン」と「静的」の本当の意味を誤解しています。