Initialisation par défaut de std :: array?

104

Avec C ++ 11 std::array, ai-je la garantie que la syntaxe std::array<T, N> x;initialisera par défaut tous les éléments du tableau?

EDIT : sinon, y a-t-il une syntaxe qui fonctionnera sur tous les tableaux (y compris les tableaux de taille zéro) pour initialiser tous les éléments à leur valeur par défaut?

EDIT : sur cppreference , la description du constructeur par défaut dit:

(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array 

donc la réponse peut être oui. Mais j'aimerais en être sûr selon la norme ou la future norme.

Vincent
la source
Ne pense pas. C'est déclaré par défaut, donc c'est fondamentalement l'équivalent de la T x[N]syntaxe.
Rapptz

Réponses:

149

Par définition, l'initialisation par défaut est l'initialisation qui se produit lorsqu'aucune autre initialisation n'est spécifiée; le langage C ++ vous garantit que tout objet pour lequel vous ne fournissez pas d'initialiseur explicite sera initialisé par défaut (C ++ 11 §8.5 / 11). Cela inclut les objets de type std::array<T, N>et T[N].

Sachez qu'il existe des types pour lesquels l'initialisation par défaut n'a aucun effet et laisse la valeur de l'objet indéterminée: tout type non-classe, non-tableau (§8.5 / 6). Par conséquent, un tableau d'objets initialisé par défaut avec de tels types aura une valeur indéterminée, par exemple:

int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;

Les tableaux de style c et std::arraysont tous deux remplis d'entiers de valeur indéterminée, tout comme plain_inta une valeur indéterminée.

Existe-t-il une syntaxe qui fonctionnera sur tous les tableaux (y compris les tableaux de taille zéro) pour initialiser tous les éléments à leur valeur par défaut?

Je suppose que lorsque vous dites «à leur valeur par défaut», vous voulez vraiment dire «initialiser tous les éléments à T{}». Ce n'est pas une initialisation par défaut , c'est une initialisation de valeur (8.5 / 7). Vous pouvez demander l'initialisation de la valeur assez facilement en C ++ 11 en donnant à chaque déclaration un initialiseur vide:

int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};

Ce qui initialisera tour à tour tous les éléments du tableau, ce qui entraînera l' plain_old_intinitialisation à zéro de tous les membres des deux types de tableaux.

Casey
la source
Et si c'est un membre de classe: struct X {std :: array <int, 12> dozen; X (): dozen () {} Est-ce que ça me rapporte douze zéros?
gerardw
4
@gerardw Selon la norme, oui. Attention aux bogues dans MSVC, il ne parvient pas à implémenter correctement certains cas d'initialisation de valeur.
Casey
1
en effet, boost le dit et contournement avec leur boost::value_initialized lien, mais je crois que VC12 (VS2013) a un bien meilleur support maintenant.
v.oddou le
1
Cela me fait souhaiter que le comité ait changé la norme en initialisation de la valeur par défaut et à la valeur minée à la demande. Ie std :: array <int, 12> = {std :: indetermined}; ou quelque chose
Viktor Sehr
En pratique, que signifie même initialiser quelque chose à une valeur indéterminée? Quelle est l'alternative?
Andrew
21

L'initialisation par défaut est un terme du Standard signifiant potentiellement aucune initialisation, donc vous voulez probablement dire initialisation zéro .

La description sur cppreference.com est en fait un peu trompeuse. std::arrayest une classe agrégée, et si le type d'élément est primitif, c'est POD: "plain old data", avec une sémantique correspondant étroitement au langage C. Le constructeur implicitement défini de std::array< int, N >est un constructeur trivial qui ne fait absolument rien.

La syntaxe comme std::array< int, 3 >()ou std::array< int, 3 > x{}qui fournit des valeurs nulles ne le fait pas en appelant un constructeur. Obtenir des zéros fait partie de l' initialisation de la valeur , spécifiée dans C ++ 11 §8.5 / 8:

Initialiser par valeur un objet de type T signifie:

- si T est un type de classe (éventuellement qualifié cv) sans constructeur par défaut fourni par l'utilisateur ou supprimé, alors l'objet est initialisé à zéro…, et si T a un constructeur par défaut non trivial, l'objet est initialisé par défaut;

std::arrayn'a pas de constructeur par défaut fourni par l'utilisateur, il est donc initialisé à zéro. Il a un constructeur par défaut défini implicitement, mais il est trivial, il n'est donc jamais initialisé par défaut. (Mais cela ne fait aucune différence puisque l'initialisation triviale par définition n'a aucun effet à l'exécution.)

sinon, existe-t-il une syntaxe qui fonctionnera sur tous les tableaux (y compris les tableaux de taille zéro) pour initialiser tous les éléments à leur valeur par défaut?

Les tableaux de style C et std::arraysont tous deux des agrégats, et la façon d'initialiser complètement à zéro tout agrégat est avec la syntaxe = {}. Cela fonctionne depuis C ++ 98. Notez que les tableaux de style C ne peuvent pas avoir d'étendue nulle et que ce sizeof (std::array< X, 0 >)n'est pas zéro.

Potatoswatter
la source
6

Les deux T x[N];et std::array<T, N> x;initialisent par défaut chaque élément du tableau.

Par exemple, si T = std::string, chaque élément sera une chaîne vide. Si Test une classe sans constructeur par défaut, les deux échoueront à se compiler. Si T = int, chaque élément aura une valeur indéterminée (sauf si cette déclaration se trouve être à la portée de l'espace de noms)

Cubbi
la source
0

Tout d'abord, T x [N] initialise par défaut les éléments, bien que l'initialisation par défaut d'un type scalaire T ne fasse rien. Ce qui précède vaut également pour std :: array x. Je pense que vous avez besoin d'une initialisation de liste.

Lingxi
la source