Standardinitialisierung von std :: array?

103

Habe std::arrayich unter C ++ 11 die Garantie, dass die Syntax std::array<T, N> x;standardmäßig alle Elemente des Arrays initialisiert?

BEARBEITEN : Wenn nicht, gibt es eine Syntax, die für alle Arrays (einschließlich Arrays mit der Größe Null) funktioniert, um alle Elemente auf ihren Standardwert zu initialisieren?

EDIT : auf cppreference , sagt die Standardkonstruktors Beschreibung:

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

Die Antwort kann also ja sein. Aber ich möchte sicher sein, dass dies dem Standard oder dem zukünftigen Standard entspricht.

Vincent
quelle
Glaube nicht. Es ist standardmäßig deklariert und entspricht im Grunde der T x[N]Syntax.
Rapptz

Antworten:

148

Standardmäßig ist die Standardinitialisierung die Initialisierung, die erfolgt, wenn keine andere Initialisierung angegeben wird. Die C ++ - Sprache garantiert Ihnen, dass alle Objekte, für die Sie keinen expliziten Initialisierer angeben, standardmäßig initialisiert werden (C ++ 11 §8.5 / 11). Das schließt Objekte vom Typ std::array<T, N>und ein T[N].

Beachten Sie, dass es Typen gibt, für die die Standardinitialisierung keine Auswirkung hat und der Wert des Objekts unbestimmt bleibt: alle Nicht-Klassen- und Nicht-Array-Typen (§8.5 / 6). Folglich hat ein standardmäßig initialisiertes Array von Objekten mit solchen Typen einen unbestimmten Wert, z.

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

Sowohl das Array im c-Stil als auch std::arraysind mit Ganzzahlen mit unbestimmtem Wert gefüllt, ebenso wie plain_intmit unbestimmtem Wert.

Gibt es eine Syntax, die für alle Arrays (einschließlich Arrays mit der Größe Null) funktioniert, um alle Elemente auf ihren Standardwert zu initialisieren?

Ich vermute, wenn Sie "zu ihrem Standardwert" sagen, meinen Sie wirklich "alle Elemente initialisieren auf T{}". Dies ist keine Standardinitialisierung , sondern eine Wertinitialisierung (8.5 / 7). Sie können die Wertinitialisierung in C ++ 11 ganz einfach anfordern, indem Sie jeder Deklaration einen leeren Initialisierer geben:

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

Dadurch werden alle Array-Elemente nacheinander wertinitialisiert, was dazu führt plain_old_int, dass alle Mitglieder beider Arten von Arrays auf Null initialisiert werden.

Casey
quelle
Was ist, wenn es sich um ein Klassenmitglied handelt: struct X {std :: array <int, 12> Dutzend; X (): Dutzend () {} Bekomme ich zwölf Nullen?
Gerardw
4
@gerardw Laut Standard ja. Vorsicht vor Fehlern in MSVC, da einige Fälle der Wertinitialisierung nicht korrekt implementiert werden.
Casey
1
In der Tat sagt Boost dies und umgeht es mit ihrem boost::value_initialized Link, aber ich glaube, VC12 (VS2013) hat jetzt eine viel bessere Unterstützung.
v.oddou
1
Ich wünschte, das Komitee hätte den Standard auf Anfrage auf Standardwertinitialisierung und unterminierten Wert geändert. Dh std :: array <int, 12> = {std :: unbestimmt}; oder so
Viktor Sehr
Was bedeutet es in der Praxis überhaupt, etwas auf einen unbestimmten Wert zu initialisieren? Was ist die Alternative?
Andrew
21

Die Standardinitialisierung ist ein Begriff aus dem Standard, der möglicherweise überhaupt keine Initialisierung bedeutet. Sie meinen also wahrscheinlich eine Nullinitialisierung .

Die Beschreibung auf cppreference.com ist eigentlich etwas irreführend. std::arrayist eine aggregierte Klasse, und wenn der Elementtyp primitiv ist, ist es POD: "einfache alte Daten", wobei die Semantik eng mit der C-Sprache übereinstimmt. Der implizit definierte Konstruktor von std::array< int, N >ist ein trivialer Konstruktor, der absolut nichts tut.

Syntax wie std::array< int, 3 >()oder std::array< int, 3 > x{}, die Nullwerte liefern, tun dies nicht durch Aufrufen eines Konstruktors. Erste Nullen ist Teil der wert Initialisierung , angegeben in C ++ 11 §8.5 / 8:

Ein Objekt vom Typ T wertinitialisieren bedeutet:

- Wenn T ein (möglicherweise lebenslaufqualifizierter) Klassentyp ohne einen vom Benutzer bereitgestellten oder gelöschten Standardkonstruktor ist, wird das Objekt mit Null initialisiert. Wenn T einen nicht trivialen Standardkonstruktor hat, wird das Objekt standardmäßig initialisiert.

std::arrayhat keinen vom Benutzer bereitgestellten Standardkonstruktor, daher wird er mit Null initialisiert. Es verfügt über einen implizit definierten Standardkonstruktor, ist jedoch trivial und wird daher niemals standardmäßig initialisiert. (Dies macht jedoch keinen Unterschied, da eine triviale Initialisierung per Definition zur Laufzeit keine Auswirkung hat.)

Wenn nicht, gibt es eine Syntax, die für alle Arrays (einschließlich Arrays mit der Größe Null) funktioniert, um alle Elemente auf ihren Standardwert zu initialisieren?

Arrays im C-Stil std::arraysind beide Aggregate, und die Möglichkeit, Aggregate vollständig auf Null zu initialisieren, liegt in der Syntax = {}. Dies funktioniert seit C ++ 98. Beachten Sie, dass Arrays im C-Stil keine Ausdehnung von Null haben können und dass dies sizeof (std::array< X, 0 >)nicht Null ist.

Kartoffelklatsche
quelle
6

Beide T x[N];und std::array<T, N> x;standardmäßig initialisieren jedes Element des Arrays.

Wenn beispielsweise, T = std::stringist jedes Element eine leere Zeichenfolge. Wenn Tes sich um eine Klasse ohne Standardkonstruktor handelt, können beide nicht kompiliert werden. Wenn T = int, hat jedes Element einen unbestimmten Wert (es sei denn, diese Deklaration befindet sich zufällig im Namespace-Bereich).

Cubbi
quelle
0

Zunächst initialisiert T x [N] die Elemente standardmäßig, obwohl die Standardinitialisierung eines Skalartyps T tatsächlich nichts bewirkt. Das Obige gilt auch für std :: array x. Ich denke, was Sie brauchen, ist eine Listeninitialisierung.

Lingxi
quelle