回答:
関数static
変数の存続期間は、プログラムフローが初めて宣言[0]に遭遇し、プログラムの終了時に終了します。これは、ランタイムが実際に構築された場合にのみそれを破壊するために、実行時に何らかのブックキーピングを実行する必要があることを意味します。
さらに、標準では静的オブジェクトのデストラクタは構築の完了とは逆の順序で実行する必要があると規定されているため[1]、構築の順序は特定のプログラムの実行に依存する可能性があるため、構築の順序を考慮する必要があります。
例
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
出力:
C:> SAMPLE.EXE
FOOで作成
fooの中で破壊されましたC:> sample.exe 1
Created in if
Created in foo
Destroyed in foo
Destroyed in ifC:> SAMPLE.EXE 1 2は、
FOOで作成され
た場合に作成され
た場合で破壊
FOOで破壊します
[0]
以来、C ++は98 [2]は、これがマルチスレッド環境で動作あろう方法、複数のスレッドへの参照は指定されていない、とのように問題となることがロディに言及しています。
[1]
C ++ 98セクション3.6.3.1
[basic.start.term]
[2]
C ++ 11では、staticはスレッドセーフな方法で初期化されます。これはMagic Staticsとも呼ばれます。
[basic.start.term]
Mottiは正しい順序ですが、他に考慮すべきことがいくつかあります。
コンパイラーは通常、非表示フラグ変数を使用して、ローカル静的変数がすでに初期化されているかどうかを示します。このフラグは、関数へのすべてのエントリーでチェックされます。明らかにこれは小さなパフォーマンスヒットですが、このフラグがスレッドセーフであることが保証されていないことがさらに問題です。
上記のようにローカルスタティックがあり、foo
複数のスレッドから呼び出された場合、競合状態が発生plonk
して、正しく初期化されなかったり、複数回実行されたりする可能性があります。また、この場合plonk
、それを構築したスレッドとは異なるスレッドによって破壊される可能性があります。
標準が言っていることにもかかわらず、ローカルの静的破壊の実際の順序には非常に注意します。なぜなら、破壊された後も静的がまだ有効であることに無意識に依存する可能性があり、これを追跡するのが本当に難しいからです。
既存の説明は、6.7にある標準からの実際のルールがなければ、完全ではありません。
静的ストレージ期間またはスレッドストレージ期間を持つすべてのブロックスコープ変数のゼロ初期化は、他の初期化が行われる前に実行されます。静的ストレージ期間を使用したブロックスコープエンティティの定数初期化は、該当する場合、そのブロックが最初に入力される前に実行されます。実装は、名前空間スコープ内の静的またはスレッドストレージ期間で変数を静的に初期化することが許可されているのと同じ条件下で、静的またはスレッドストレージ期間で他のブロックスコープ変数の初期初期化を実行することが許可されます。そうでない場合、そのような変数は、コントロールがその宣言を最初に通過するときに初期化されます。このような変数は、初期化が完了すると初期化されたと見なされます。初期化が例外をスローして終了した場合、初期化が完了していないため、次にコントロールが宣言に入るときに再試行されます。変数の初期化中に制御が宣言に同時に入ると、同時実行は初期化の完了を待ちます。変数が初期化されている間に制御が宣言に再帰的に入る場合、動作は未定義です。
FWIW、Codegear C ++ Builderは、標準に従って予想される順序で破棄しません。
C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if
...これは破壊命令に依存しない別の理由です!
静的変数は、一度遊びに来ているプログラムの実行を開始すると、それは、プログラムの実行が終了するまで、引き続き使用可能。
静的変数は、メモリのデータセグメントに作成されます。