1
votes

Le constructeur par défaut généré par le compilateur initialisera-t-il les pointeurs de std :: array à nullptr?

Est-il correct que compte tenu du code ci-dessous, le compilateur devrait générer Node () qui devrait appeler std :: array () qui devrait initialisez les 100 pointeurs sur nullptr.

Remarque: je sais que je peux y arriver si j'utilise std :: array children {}; , mais je ne le suis pas essayant de faire fonctionner mon code (c'est déjà le cas), j'essaie de m'assurer qu'il ne fonctionne pas par accident.

struct Node
{
    int value;
    std::array<Node *, 100> children {};
}

struct Node
{
    Node() : children{} {}
    int value;
    std::array<Node *, 100> children;
}

Mise à jour:

Ici les pointeurs sont des ordures:

struct Node
{
    int value;
    std::array<Node *, 100> children;
}

struct Node
{
    Node() : children() {}
    int value;
    std::array<Node *, 100> children;
}

Ici les pointeurs sont nullptr:

struct Node
{
    int value;
    std::array<Node *, 100> children;
}

S'il vous plaît, corrigez-moi si je me trompe.


1 commentaires

Ce que vous voulez, c'est utiliser shared_ptr au lieu de pointeurs nus. Beaucoup moins de surprises à la fin tant que vous les utilisez partout (systématiquement).


3 Réponses :


0
votes

Tant qu'une valeur n'est pas affectée à un pointeur, il pointe par défaut vers une adresse "garbage". Le compilateur ne leur attribue pas la valeur par défaut nullptr . En fait, il n'attribue aucune valeur "par défaut" aux pointeurs.
Modifier:
À partir de la documentation pour std :: array :

notez que l'initialisation par défaut peut entraîner des valeurs indéterminées pour les non-classe T

Donc, si vous utilisez le constructeur par défaut, vous devez attribuer vous-même à chaque élément une valeur de nullptr .


0 commentaires

5
votes

Pour citer cppreference sur le constructeur de std :: tableau :

initialise le tableau en suivant les règles d'initialisation de l'agrégat (notez que l'initialisation par défaut peut entraîner des valeurs indéterminées pour les non-classe T)

En déclarant votre variable comme std :: array children; vous invoquez le constructeur par défaut. Et, selon les règles d'initialisation, les POD ( int , char , double , pointeurs, ...) ne sont pas initialisés par défaut. Donc non, votre tableau ne sera pas initialisé avec nullptr si vous n'utilisez pas l'initialisation agrégée.

Initialisation agrégée

Node x;
std::array<Node *, 100> children = {&x};

appelle le constructeur par défaut, mais aucun initialiseur d'agrégat n'est donné, donc l'initialisation d'agrégat ne se produira pas. Cependant

std::array<Node *, 100> children{}
std::array<Node *, 100> children = {};

non seulement appelle le constructeur par défaut, mais effectue également une initialisation d'agrégat. Dans ce cas, l'agrégat {} est juste vide. Et, en suivant les règles d'initialisation agrégée, s'il y a moins d'initialiseurs que de membres de données, chaque membre non initialisé sera initialisé par défaut. Ainsi

std::array<Node *, 100> children;

par exemple, initialisera le premier élément du tableau avec le pointeur vers x et chaque élément successif sera initialisé par défaut à nullptr .


3 commentaires

J'ajouterais une clarification: non, le tableau ne sera pas initialisé avec nullptr si Node est initialisé par défaut .


Une partie de la terminologie est perdue pour moi ... std :: array children {}; initialisera les 100 pointeurs à nullptr selon ceci: stackoverflow.com/questions/35849693/… Cela signifie-t-il que Node (): children () {} ne le fait pas, mais Node (): children { } {} le ferait?


Incroyable, c'est très propre maintenant. Merci!



1
votes

Selon cette réponse , l'initialisation par défaut d'un std :: array des pointeurs ne initialisera pas les pointeurs qu'il contient, et leurs valeurs seront indéterminées.

Node::Node() : children{/* value init array */} {/* empty c'tor body */}

Vous pouvez cependant utiliser valeur initialisation pour initialiser tous les pointeurs contenus vers nullptr . Sur un std :: array , cela a pour effet d'initialiser la valeur de chaque valeur du tableau, qui à son tour initialise à zéro chaque pointeur.

std::array<Node *, 100> children {}; // pointers are all null

Dans une liste d'initialiseurs de membres, vous pouvez également le faire comme suit:

std::array<Node *, 100> children; // pointers are uninitialized


0 commentaires