Value-initialization
Dies ist die Initialisierung, die durchgeführt wird, wenn ein Objekt mit einem leeren Initialisierer konstruiert wird.
Inhaltsverzeichnis |
Syntax
T
()
|
(1) | ||||||||
new
T
()
|
(2) | ||||||||
Class
::
Class
(
...
)
:
member
()
{
...
}
|
(3) | ||||||||
T
object
{};
|
(4) | (seit C++11) | |||||||
T
{}
|
(5) | (seit C++11) | |||||||
new
T
{}
|
(6) | (seit C++11) | |||||||
Class
::
Class
(
...
)
:
member
{}
{
...
}
|
(7) | (seit C++11) | |||||||
Erklärung
Wertinitialisierung wird in diesen Situationen durchgeführt:
In allen Fällen, wenn das leere Paar geschweifter Klammern
{}
verwendet wird und
T
ein Aggregattyp ist,
wird anstelle der Wertinitialisierung
aggregate initialization
durchgeführt.
|
Wenn
|
(seit C++11) |
Die Auswirkungen der Wertinitialisierung sind:
-
Wenn
Tein (möglicherweise cv-qualifizierter) Klassentyp ist:
-
-
Falls die Standardinitialisierung für
Teinen Konstruktor auswählt und der Konstruktor nicht benutzerdeklariert (bis C++11) benutzerbereitgestellt (seit C++11) ist, wird das Objekt zunächst nullinitialisiert . - In jedem Fall wird das Objekt standardinitialisiert .
-
Falls die Standardinitialisierung für
-
Andernfalls, falls
Tein Array-Typ ist, wird jedes Element des Arrays wertinitialisiert. - Andernfalls wird das Objekt nullinitialisiert.
Hinweise
Die Syntax
T object
(
)
;
initialisiert kein Objekt; sie deklariert eine Funktion ohne Parameter, die
T
zurückgibt. Die Methode zur Wertinitialisierung einer benannten Variable vor C++11 war
T object
=
T
(
)
;
, die einen temporären Wert initialisiert und dann das Objekt kopierinitialisiert: Die meisten Compiler
optimieren die Kopie in diesem Fall weg
.
Referenzen können nicht wertinitialisiert werden.
Wie beschrieben in
function-style cast
, ist die Syntax
T
(
)
(1)
verboten, wenn
T
einen Array-Typ benennt, während
T
{
}
(5)
erlaubt ist.
Alle Standardcontainer (
std::vector
,
std::list
, etc.) wertinitialisieren ihre Elemente, wenn sie mit einem einzelnen
size_type
-Argument konstruiert werden oder wenn sie durch einen Aufruf von
resize
(
)
vergrößert werden, es sei denn, ihr Allokator passt das Verhalten von
construct
an.
Beispiel
#include <cassert> #include <iostream> #include <string> #include <vector> struct T1 { int mem1; std::string mem2; virtual void foo() {} // stellt sicher, dass T1 kein Aggregat ist }; // impliziter Standardkonstruktor struct T2 { int mem1; std::string mem2; T2(const T2&) {} // benutzerdefinierter Kopierkonstruktor }; // kein Standardkonstruktor struct T3 { int mem1; std::string mem2; T3() {} // benutzerdefinierter Standardkonstruktor }; std::string s{}; // Klasse => Standardinitialisierung, der Wert ist "" int main() { int n{}; // Skalar => Nullinitialisierung, der Wert ist 0 assert(n == 0); double f = double(); // Skalar => Nullinitialisierung, der Wert ist 0.0 assert(f == 0.0); int* a = new int[10](); // Array => Wertinitialisierung jedes Elements assert(a[9] == 0); // der Wert jedes Elements ist 0 T1 t1{}; // Klasse mit implizitem Standardkonstruktor => assert(t1.mem1 == 0); // t1.mem1 ist nullinitialisiert, der Wert ist 0 assert(t1.mem2 == ""); // t1.mem2 ist standardinitialisiert, der Wert ist "" // T2 t2{}; // Fehler: Klasse ohne Standardkonstruktor T3 t3{}; // Klasse mit benutzerdefiniertem Standardkonstruktor => std::cout << t3.mem1; // t3.mem1 ist standardinitialisiert auf unbestimmten Wert assert(t3.mem2 == ""); // t3.mem2 ist standardinitialisiert, der Wert ist "" std::vector<int> v(3); // Wertinitialisierung jedes Elements assert(v[2] == 0); // der Wert jedes Elements ist 0 std::cout << '\n'; delete[] a; }
Mögliche Ausgabe:
42
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 178 | C++98 |
Es gab keine Wertinitialisierung; leere Initialisierer riefen Standard-
initialisierung auf (obwohl new T ( ) auch Nullinitialisierung durchführte) |
Leere Initialisierer rufen
Wertinitialisierung auf |
| CWG 543 | C++98 |
Wertinitialisierung für ein Klassenobjekt ohne benutzer-
bereitgestellte Konstruktoren entsprach der Wert- initialisierung jedes Teilobjekts (was ein Mitglied mit benutzerbereitgestelltem Standardkonstruktor nicht null- initialisieren muss) |
Nullinitialisiert
das gesamte Objekt, dann wird der Standardkonstruktor aufgerufen |
| CWG 1301 | C++11 |
Wertinitialisierung von Unions mit gelöschten
Standardkonstruktoren führte zu Nullinitialisierung |
Sie werden
standardinitialisiert |
| CWG 1368 | C++98 |
Jeder benutzerbereitgestellte Konstruktor verursachte,
dass die Nullinitialisierung übersprungen wurde |
Nur ein benutzerbereitgestellter
Standardkonstruktor überspringt Nullinitialisierung |
| CWG 1502 | C++11 |
Wertinitialisierung einer Union ohne benutzerbereitgestellten
Standardkonstruktor nullinitialisierte nur das Objekt, trotz Standardmitgliedsinitialisierern |
Führt Standard-
initialisierung nach Nullinitialisierung durch |
| CWG 1507 | C++98 |
Wertinitialisierung für ein Klassenobjekt ohne
benutzerbereitgestellte Konstruktoren überprüfte nicht die Gültigkeit des Standardkonstruktors, wenn dieser trivial ist |
Die Gültigkeit des trivialen
Standardkonstruktors wird überprüft |
| CWG 2820 | C++98 |
Die Standardinitialisierung nach der Null-
initialisierung erforderte einen nicht-trivialen Konstruktor |
Nicht erforderlich |
| CWG 2859 | C++98 |
Wertinitialisierung für ein Klassenobjekt könnte
Nullinitialisierung beinhalten, selbst wenn die Standard- initialisierung keinen benutzerbereitgestellten Konstruktor auswählt |
In diesem Fall gibt es
keine Nullinitialisierung |