4

重要なコンストラクターを使用するC++11のグローバル変数は、静的初期化フェーズでmainに入る前に作成されます。

同様に、非関数ローカルのthread_local変数は、スレッドごとの「thread_local初期化フェーズ」中に作成されます。

C ++ 11標準では、これらの変数を作成する順序を指定していますか?どちらの場合も、2つの変数がある場合:

// global scope

A::A() { b.f(); }  // A constructor uses global b

A a;
B b;

C ++ 11標準では、初期化する順序を指定していますか、それとも変数を初期化せずに使用するとエラーが発生するように指定されていますか?

非関数ローカルthread_localの場合も同様です。

// global scope

A::A() { b.f(); }  // A constructor uses global b

thread_local A a;
thread_local B b;

標準は、構築する必要のある順序を指定していますか?また、変数が初期化される前に別のコンストラクターから使用された場合に何が起こるかを定義していますか?

回答を得るための主張を裏付けるために、 C++11標準リファレンスを提供してください。

4

2 に答える 2

2

「重要なコンストラクターを持つC++11のグローバル変数は、静的初期化フェーズ中にmainに入る前に構築されます。」というあなたのステートメント。完全に真実ではないようです-動的初期化フェーズまで初期化されない可能性があります

最初のaとbが「順序付き初期化」の変数の場合、標準では次のようになります。

単一の変換ユニット内で定義された順序付き初期化を持つ変数は、変換ユニット内で定義された順序で初期化されるものとします。

3.6.2/2はこれをすべてカバーしています。

編集:私があなたの2番目のaとbに初期化の順序がなく、どちらの順序でも初期化できることがわかる限り。しかし、私は何かが欠けているかもしれません。

于 2012-10-28T16:24:21.893 に答える
2

静的ストレージ期間については、Alanの回答に同意します。初期化が同じ変換単位にある場合、それらの動的初期化はそれらのオブジェクト定義の順序です。コンパイラーはb、(3.6.2 / 3に従って)方法を理解できる場合は、代わりに静的初期化として初期化することができます。したがって、最初のプログラムは未定義の動作を呼び出す場合と呼び出さない場合があり、おそらく悪い考えです。

動的ストレージ期間については、3.7.2/2に注意してください。

スレッドの保存期間を持つ変数は、最初のodr-use(3.2)の前に初期化され、構築された場合は、スレッドの終了時に破棄されます。

したがって、スレッドローカル変数は、名前空間スコープの静的変数というよりも、関数ローカルの静的変数のように機能します。2番目のプログラムには未定義の動作はありません。

于 2012-10-28T17:35:35.630 に答える