web-dev-qa-db-fra.com

Initialisation d'un tableau de membres dans l'initialiseur du constructeur

class C 
{
public:
 C() : arr({1,2,3}) //doesn't compile
{}
    /*
    C() : arr{1,2,3} //doesn't compile either
{}
    */
private:
 int arr[3];
};

Je pense que la raison en est que les tableaux ne peuvent être initialisés qu'avec = syntaxe, c'est-à-dire:

int arr[3] = {1,3,4};

Des questions

  1. Comment puis-je faire ce que je veux faire (c'est-à-dire initialiser un tableau dans un constructeur (ne pas affecter d'éléments dans le corps)). Est-ce même possible?
  2. La norme C++ 03 dit-elle quelque chose de spécial sur l'initialisation d'agrégats (y compris de tableaux) dans les initialiseurs ctor? Ou l'invalidité du code ci-dessus est-elle un corollaire de certaines autres règles?
  3. Les listes d'initialisation C++ 0x résolvent-elles le problème?

P.S. Veuillez ne pas mentionner les vecteurs, boost :: tableaux, et leur supériorité par rapport aux tableaux, ce dont je suis bien conscient.

89
Armen Tsirunyan
  1. Comment puis-je faire ce que je veux faire (c’est-à-dire initialiser un tableau dans un constructeur (ne pas assigner d’éléments dans le corps)). Est-ce même possible?

Oui. Il utilise une structure contenant un tableau. Vous dites que vous êtes déjà au courant, mais je ne comprends pas la question. De cette façon, vous initialisez un tableau dans le constructeur, sans affectation dans le corps. C'est quoi boost::array Est-ce que.

La norme C++ 03 dit-elle quelque chose de spécial sur l'initialisation d'agrégats (y compris de tableaux) dans les initialiseurs ctor? Ou l'invalidité du code ci-dessus est-elle un corollaire de certaines autres règles?

Un mem-initializer utilise l'initialisation directe. Et les règles de l'article 8 interdisent ce genre de chose. Je ne suis pas tout à fait sûr du cas suivant, mais certains compilateurs le permettent.

struct A {
  char foo[6];
  A():foo("hello") { } /* valid? */
};

Voir ce GCC PR pour plus de détails.

Les listes d'initialisation C++ 0x résolvent-elles le problème?

Oui, ils le font. Cependant, votre syntaxe n'est pas valide, je pense. Vous devez utiliser des accolades directement pour lancer l'initialisation de la liste

struct A {
  int foo[3];
  A():foo{1, 2, 3} { }
  A():foo({1, 2, 3}) { } /* invalid */
};
51

C++ 98 ne fournit pas de syntaxe directe pour tout ce qui concerne la mise à zéro (ou pour les éléments non-POD, l'initialisation d'une valeur) du tableau. Pour cela, vous écrivez simplement C(): arr() {}.

Je pense que Roger Pate a tort en ce qui concerne les limitations alléguées de l'initialisation de l'agrégat C++ 0x, mais je suis trop paresseux pour l'examiner ou l'examiner, et cela n'a pas d'importance, n'est-ce pas? EDIT : Roger parlait de "C++ 03", je l’ai mal interprété comme "C++ 0x". Désolé, Roger. ☺

Une solution de contournement C++ 98 pour votre code actuel consiste à envelopper le tableau dans un struct et à l'initialiser à partir d'une constante statique de ce type. Les données doivent résider quelque part de toute façon. Cela peut ressembler à ça:

class C 
{
public:
    C() : arr( arrData ) {}

private:
     struct Arr{ int elem[3]; };
     Arr arr;
     static Arr const arrData;
};

C::Arr const C::arrData = {{1, 2, 3}};
28

Solution de contournement:

template<class T, size_t N>
struct simple_array { // like std::array in C++0x
   T arr[N];
};


class C : private simple_array<int, 3> 
{
      static simple_array<int, 3> myarr() {
           simple_array<int, 3> arr = {1,2,3};
           return arr;
      }
public:
      C() : simple_array<int, 3>(myarr()) {}
};
6
Alexey Malistov
  1. Non malheureusement.
  2. Vous ne pouvez pas comme vous le souhaitez, car la grammaire ne le permet pas (voir plus bas). Vous pouvez uniquement utiliser une initialisation de type ctor et, comme vous le savez, elle n'est pas disponible pour initialiser chaque élément dans des tableaux.
  3. Je crois que oui, dans la mesure où ils généralisent l’initialisation de nombreuses manières utiles. Mais je ne suis pas sûr des détails.

En C++ 03, l'initialisation d'agrégat s'applique uniquement avec une syntaxe similaire à celle décrite ci-dessous, qui doit être une instruction distincte et ne rentre pas dans un initialiseur ctor.

T var = {...};
3
Roger Pate

Que diriez-vous

...
  C() : arr{ {1,2,3} }
{}
...

?

Compile bien sur g ++ 4.8

1
eold