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
, 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.
3 Réponses :
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
.
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
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.
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
.
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
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!
Selon cette réponse , l'initialisation par défaut d'un Vous pouvez cependant utiliser valeur initialisation pour initialiser tous les pointeurs contenus vers Dans une liste d'initialiseurs de membres, vous pouvez également le faire comme suit: 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 */}
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
std::array<Node *, 100> children; // pointers are uninitialized
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).