web-dev-qa-db-fra.com

Membre du tableau Zero-Initialize dans la liste d'initialisation

J'ai une classe avec un membre du tableau que je voudrais initialiser à tous les zéros.

class X
{
private:
    int m_array[10];
};

Pour une variable locale, il existe un moyen simple d'initialiser zéro (voir ici ):

int myArray[10] = {};

De plus, le membre de la classe m_array doit clairement être initialisé, car les entiers à initialisation par défaut laisseront simplement des déchets aléatoires, comme expliqué ici .

Cependant, je peux voir deux façons de procéder pour un tableau de membres:

Avec des parenthèses:

public:
    X()
    : m_array()
    {}

Avec bretelles:

public:
    X()
    : m_array{}
    {}

Les deux sont-ils corrects? Y a-t-il une différence entre les deux en C++ 11?

25
ValarDohaeris

Initialisation d'un membre avec () effectue l'initialisation de la valeur.

Initialisation de tout type de classe avec un constructeur par défaut avec {} effectue l'initialisation de la valeur.

Initialisation de tout autre type d'agrégat (y compris les tableaux) avec {} effectue l'initialisation de la liste et équivaut à initialiser chacun des membres de l'agrégat avec {}.

Initialisation de tout type de référence avec {} construit un objet temporaire, qui est initialisé à partir de {}, et lie la référence à ce temporaire.

Initialisation de tout autre type avec {} effectue l'initialisation de la valeur.

Par conséquent, pour à peu près tous les types, l'initialisation à partir de {} donnera le même résultat que l'initialisation de la valeur. Vous ne pouvez pas avoir de tableaux de références, ils ne peuvent donc pas faire exception. Vous pourriez être capable de construire des tableaux de types de classes agrégées sans constructeur par défaut, mais les compilateurs ne sont pas d'accord sur les règles exactes. Mais pour revenir à votre question, tous ces cas d'angle n'ont pas vraiment d'importance pour vous: pour votre type d'élément de tableau spécifique, ils ont exactement le même effet.

16
user743382

Les types d'initialisation peuvent être assez fastidieux à parcourir, mais dans ce cas, ils sont triviaux. Pour:

public:
    X()
    : m_array()
    {}

puisque la liste d'expressions entre les parenthèses est vide, une initialisation de valeur se produit. De même pour:

public:
    X()
    : m_array{}
    {}

l'initialisation de la liste se produit, puis l'initialisation de la valeur car la accolade-init-list est vide.


Pour donner une réponse plus complète, passons au §8.5 de N4140.

  1. Si aucun initialiseur n'est spécifié pour un objet, l'objet est initialisé par défaut. Lorsqu'un stockage pour un objet avec une durée de stockage automatique ou dynamique est obtenu, l'objet a une valeur indéterminée , et si aucune initialisation n'est effectuée pour l'objet, l'objet conserve une valeur indéterminée jusqu'à ce que cette valeur soit remplacée (5.17).

Cette valeur indéterminée est ce que vous appelez des valeurs de déchets.

  1. Pour initialiser à zéro un objet ou une référence de type T signifie:

    - si T est un type tableau, chaque élément est initialisé à zéro

  2. Pour initialiser une valeur un objet de type T signifie:

    - si T est un type de classe (éventuellement qualifié cv) ... alors l'objet est initialisé par défaut; ...

    - si T est un type de tableau, alors chaque élément est initialisé en valeur;

    - sinon, l'objet est initialisé à zéro.

  3. La sémantique des initialiseurs est la suivante. ... - Si l'initialiseur est une (non-parenthèse) braced-init-list , l'objet ou la référence est initialisé par liste (8.5.4 ).

    - Si l'initialiseur est (), l'objet est initialisé en valeur.

Jusqu'à présent, il est clair que l'initialisation de la valeur rendra chaque élément du tableau nul puisque int n'est pas un type de classe. Mais nous n'avons pas encore couvert l'initialisation de liste et l'initialisation d'agrégat, puisqu'un tableau est un agrégat.

§8.5.4:

  1. L'initialisation de liste d'un objet ou d'une référence de type T est définie comme suit:

    - Si T est un agrégat, l'initialisation de l'agrégat est effectuée (8.5.1).

Et revenons au §8.5.1:

  1. S'il y a moins de clauses d'initialisation dans la liste qu'il y a de membres dans l'agrégat, alors chaque membre non explicitement initialisé sera initialisé à partir de son initialiseur d'accolade ou égal ou, s'il n'y a pas initialiseur d'accolade ou égal , à partir d'une liste d'initialisation vide (8.5.4).

Et nous terminons à nouveau avec le §8.5.4:

  1. L'initialisation de liste d'un objet ou d'une référence de type T est définie comme suit:

    - Sinon, si la liste d'initialisation ne contient aucun élément, l'objet est initialisé en valeur.

Puisque traverser le (projet) standard peut vous couper le souffle, je recommande cppreference car il le décompose plutôt bien.

Liens pertinents:

cppreference:

Projet de norme:

13
user3920237