この動作は明確に定義されていますか?
class Foo
{
int A, B;
public:
Foo(int Bar): B(Bar), A(B + 123)
{
}
};
int main()
{
Foo MyFoo(0);
return 0;
}
この動作は明確に定義されていますか?
class Foo
{
int A, B;
public:
Foo(int Bar): B(Bar), A(B + 123)
{
}
};
int main()
{
Foo MyFoo(0);
return 0;
}
いいえ、未定義です。A
最初に初期化され(クラス定義の最初)、初期化されていないを使用しますB
。
クラスメンバーは、初期化リストでの順序に関係なく、クラス定義に表示される順序で初期化されます。実際、メンバー定義の順序を初期化リストの順序と一致させないことは悪い習慣です。
のように、のインスタンスにFoo
静的な期間がある場合Foo f(0); int main(){}
、動作は明確に定義されています。静的期間のオブジェクトは、他の初期化が行われる前にゼロで初期化されます。その場合、コンストラクターが実行されると0になりますA
。B
ただし、その後の動作は同じです。最初A
に、 123の値と(まだ醜い)の値をB
与えます。A
B
Bar
いいえ、初期化の順序は、クラス自体の宣言の順序によって定義されます。
C ++標準から12.6.2 [class.base.init] p5
:
初期化は次の順序で進行します。—
最初に、以下で説明する最も派生したクラスのコンストラクターの場合のみ、仮想基本クラスは、有向の深さ優先の左から右へのトラバーサルに表示される順序で初期化されます。基本クラスの非巡回グラフ。「左から右」は、派生クラスの基本指定子リストでの基本クラス名の出現順序です。
—次に、直接基本クラスは、(mem-initializersの順序に関係なく)base-specifier-listに表示される宣言順序で初期化されます。
—次に、非静的データメンバーは、クラス定義で宣言された順序で初期化されます(ここでも、mem-initializersの順序に関係なく)。
—最後に、コンストラクターの本体が実行されます。
[注:初期化の逆の順序でベースおよびメンバーのサブオブジェクトが確実に破棄されるように、宣言の順序が義務付けられています。]
初期化は、コンストラクターで記述した順序ではなく、宣言に表示された順序で行われます。
この質問を見てください、それは幾分似ています: 初期化リスト*引数*評価順序