web-dev-qa-db-ja.com

C ++クラスの初期化リストでmember-structを初期化する方法は?

私はc ++で次のクラス定義を持っています:

struct Foo {
  int x;
  char array[24];
  short* y;
};

class Bar {
  Bar();

  int x;
  Foo foo;
};

そして、Barクラスの初期化子で「foo」構造体(およびそのすべてのメンバー)をゼロに初期化します。これはこの方法で行うことができます:

Bar::Bar()
  : foo(),
    x(8) {
}

...?

または、初期化子リストでfoo(x)は正確に何をしますか?

または、構造体はコンパイラから自動的にゼロに初期化されますか?

45
Jan Rüegg

まず第一に、あなたはこれを読む必要があります! c ++ faq PODと集約について。あなたの場合、Fooは実際にPODクラスであり、foo()value initializationです。

タイプTのオブジェクトを値で初期化するとは、次のことを意味します。

  • tがユーザー宣言コンストラクター(12.1)を持つクラス型(9節)の場合、デフォルトのコンストラクター
    Tが呼び出されます(Tにアクセス可能なデフォルトコンストラクターがない場合、初期化は不正な形式です)。
  • tがユーザー宣言コンストラクターを持たない非共用クラス型である場合、Tのすべての非静的データメンバーとベースクラスコンポーネントは値で初期化されます。
  • tが配列型の場合、各要素は値で初期化されます。
  • それ以外の場合、オブジェクトはゼロで初期化されます

はい、fooはゼロで初期化されます。 Barコンストラクターからこの初期化を削除した場合、foodefault-initializedのみになることに注意してください。

オブジェクトに初期化子が指定されておらず、オブジェクトが(おそらくcv修飾された)非PODクラス型(またはその配列)である場合、オブジェクトはデフォルトで初期化されます。オブジェクトがconst修飾型である場合、基礎となるクラス型にはユーザーが宣言したデフォルトコンストラクターが必要です。 それ以外の場合、非静的オブジェクトに初期化子が指定されていない場合、オブジェクトとそのサブオブジェクト(存在する場合)の初期値は不定です;

50
icecrime

標準C++では、Fooのctorを作成する必要があります。

_struct Foo {

  Foo(int const a, std::initializer_list<char> const b, short* c)
    : x(a), y(c) {
    assert(b.size() >= 24, "err");
    std::copy(b.begin(), b.begin() + 24, array);
  }

  ~Foo() { delete y; }

  int x;
  char array[24];
  short* y;
};

class Bar {

  Bar() : x(5), foo(5, {'a', 'b', ..., 'y', 'z'},
    new short(5)) { }

  private:

  int x;
  Foo foo;
};
_

C++ 0xでは、統一された初期化リストを使用できますが、それでもFooにはdtorが必要です。

_class Bar {

  Bar() : x(5), foo{5, new char[24]{'a', 'b', ..., 'y', 'z'},
    new short(5)} { }
  ~Bar() { delete[] foo.array; delete foo.y;}
  }
  private:

  int x;
  Foo foo;
};
_

fooをデフォルトで初期化するには(Bar() : foo(), x(8) { }として)Fooにデフォルトのctorを与える必要があります。

8
erjot