2009-11-21 8 views
8

d1の初期化子がまだ構築されていないd2(正しい?)に渡されるので、Dのコピーコンストラクタのd.jは初期化されていないメモリアクセスですか?初期化の順序は標準によって保証されていますか?

struct D 
{ 
    int j; 

    D(const D& d) { j = d.j; } 
    D(int i) { j = i; } 
}; 

struct A 
{ 
    D d1, d2; 
    A() : d2(2), d1(d2) {} 
}; 

データメンバーの初期化の順序については、どのセクションで説明していますか?

+0

関連はありません質問:http://stackoverflow.com/questions/1589950/initializer-list-argument-evaluation-order –

答えて

11

私はこのセクションを引用することはできませんが、構造やクラスメンバーの初期化は常にが宣言された順序で起こります。コンストラクタの初期化子リストにメンバーが記述されている順序は関係ありません。

 
     -Wreorder (C++ only) 
      Warn when the order of member initializers given in the code does 
      not match the order in which they must be executed. For instance: 

        struct A { 
        int i; 
        int j; 
        A(): j (0), i (1) { } 
        }; 

      The compiler will rearrange the member initializers for i and j to 
      match the declaration order of the members, emitting a warning to 
      that effect. This warning is enabled by -Wall. 
+5

これは、物事が構築された逆の順序で破棄されるためです。順序メンバーがデストラクタの後で破棄されるように変更することはできません。したがって、構築された順序は対応していなければなりません。 – GManNickG

+2

ただし、ここで説明したように、以前に初期化されたメンバーを参照することはできます。http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.7 – Jherico

+1

この場合のFAQの説明は、おもう;スタンダードは "各基盤とメンバーの初期化後にシーケンスポイントがある"と述べている(12.6.2/3)。 –

1

はい:

GCCは順序が異なる場合警告する警告-Wreorderを持っています。良いコンパイラはA::d2A::d1の後に初期化されることを警告します。

6

あなたの例では、失敗します。

struct A 
{ 
    D d1, d2;  
    A() : d2(2), d1(d2) {} 
}; 

d1: is initialised first as it is declared first. 
d2: is then initialized. 

を結果として初期化リストは、無効なオブジェクト(D2)への参照を使用して、D1を構築します。

これは、コンパイラの警告レベルを可能な限り高くする1つの理由です。
さらに、すべての警告をエラーとして報告するように強制します。

2

この現象は、MeyerのEffective C++のItem 13で説明/強調されています。デストラクタはコンストラクタの逆順で要素を破壊しなければならないと言うので、すべてのコンストラクタは同じ順序で要素を初期化しなければならないため、(初期化リストのシーケンスの代わりに)宣言された順序で初期化します。 。

11

C++標準(ISO/IEC 14882:2003 12.6.2/5、拠点とメンバーの初期化)は言う:

初期化は次の順序で進行しなければならない。

- まず、以下で説明するように最も派生したクラスのコンストラクタに対してのみ、仮想基底クラスは、基底クラスの有向非循環グラフの深さ優先の左から右への走査に現れる順序で初期化されなければならない。 -right "は、派生クラスの基底クラス名の出現順です。 クラスの基本指定rリスト。

- 直接基底クラスは、(mem-initializerの順序にかかわらず)base-specifier-listに現れるように、宣言順に初期化されなければならない。

- 非静的データメンバは、クラス定義で宣言された順に(mem-initializerの順序にかかわらず)初期化されます。

- 最後に、コンストラクタの本体が実行されます。

箇条書き3は、非静的データメンバの初期化の順序を保証します。

関連する問題