web-dev-qa-db-fra.com

Comment initialiser la structure de membre dans la liste d'initialisation de la classe C ++?

J'ai les définitions de classe suivantes en c ++:

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

class Bar {
  Bar();

  int x;
  Foo foo;
};

et souhaite initialiser la structure "foo" (avec tous ses membres) à zéro dans l'initialiseur de la classe Bar. Cela peut-il être fait de cette façon:

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

...?

Ou que fait exactement foo (x) dans la liste d'initialisation?

Ou la structure est-elle même initialisée automatiquement à zéro à partir du compilateur?

45
Jan Rüegg

Tout d'abord, vous devriez (devez!) Lire ceci c ++ faq concernant le POD et les agrégats. Dans votre cas, Foo est en effet une classe POD et foo() est une initialisation de valeur :

Pour initialiser en valeur un objet de type T, cela signifie:

  • si T est un type de classe (article 9) avec un constructeur déclaré par l'utilisateur (12.1), alors le constructeur par défaut
    pour T est appelé (et l'initialisation est mal formée si T n'a pas de constructeur par défaut accessible);
  • si T est un type de classe non-union sans constructeur déclaré par l'utilisateur, alors chaque membre de données non statique et composant de classe de base de T est initialisé en valeur;
  • si T est un type de tableau, alors chaque élément est initialisé en valeur;
  • sinon, l'objet est initialisé à zéro

Alors oui, foo sera initialisé à zéro. Notez que si vous supprimiez cette initialisation du constructeur Bar, foo ne serait initialisé par défaut :

Si aucun initialiseur n'est spécifié pour un objet et que l'objet est de type de classe (éventuellement qualifié par cv) non POD (ou un tableau de celui-ci), l'objet doit être initialisé par défaut; si l'objet est de type qualifié const, le type de classe sous-jacent doit avoir un constructeur par défaut déclaré par l'utilisateur. Sinon, si aucun initialiseur n'est spécifié pour un objet non statique, l'objet et ses sous-objets, le cas échéant, ont une valeur initiale indéterminée ;

50
icecrime

En C++ standard, vous devez créer un ctor pour Foo.

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;
};

En C++ 0x, vous pouvez utiliser une liste d'initialisation uniforme, mais vous avez toujours besoin de dtor pour Foo:

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;
};

Pour initialiser par défaut foo (comme Bar() : foo(), x(8) { }), vous devez donner à Foo un ctor par défaut.

8
erjot