2

初期化子リストを使用して次のようなことに何度か遭遇しましたが、うまく説明できませんでした。以下が正確に失敗する理由を誰でも説明できますか (タイプミスをキャッチするコンパイラがないので、ご容赦ください)。

class Foo
{
 public:
  Foo( int i ) : m_i( i ) {}  //works with no problem

  int getInt() {return m_i;}

  ~Foo() {}
 private:
  int m_i;
};

class Bar
{
 public:
  Bar() : 
   m_foo( 5 ),           //this is ok 
   m_myInt( m_foo.getInt() ) //runtime error, seg 11
  {}

  ~Bar() {}
 private:
        Foo m_foo;
  int m_myInt;


};

初期化子リストの上位で初期化されたメンバーのメンバー関数を呼び出そうとすると、seg fault が発生します。これは既知の問題 (またはおそらく設計によるもの) であることを思い出すようですが、よく説明されているのを見たことがありません。添付の例は単純な古いデータ型で作成されBar::m_myIntていますが、デフォルト (空の) コンストラクターを持たない別のオブジェクトに置き換えると、問題はより現実的になります。誰でも私を啓発できますか?

4

2 に答える 2

9

初期化の順序は、初期化リスト内の要素の順序とは無関係です。実際の順序は、クラス定義のメンバーの順序です。つまり、あなたの例では、初期化リストのためではなく、メンバーがクラスの最初に現れるため、m_foo前に初期化されます。m_myInt

投稿した具体的な例は、問題なくコンパイルおよび実行されるはずです。

于 2010-05-04T20:31:08.297 に答える
3

データメンバーは、クラス宣言にリストされている順序で初期化されます(例では下の順序private:)。初期化子リストで指定された順序は、構築順序を妨げるものではありません。

したがって、あなたの例では、データ メンバーをそのように並べ替えると、未定義の動作が発生する可能性があります。

private:
    int m_myInt;
    Foo m_foo;

データ メンバーの順序が実際に示したものと異なる可能性はありますか?

于 2010-05-04T20:34:02.970 に答える