Namespaces
Variants

Value-initialization

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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:

1,5) wenn ein namenloses temporäres Objekt mit einem Initialisierer erstellt wird, der aus einem leeren Paar von Klammern besteht oder geschweiften Klammern (seit C++11) ;
2,6) wenn ein Objekt mit dynamischer Speicherdauer durch einen new -Ausdruck erstellt wird, mit einem Initialisierer bestehend aus einem leeren Klammerpaar oder geschweiften Klammern (seit C++11) ;
3,7) wenn ein nicht-statisches Datenelement oder eine Basisklasse mit einem Member-Initialisierer mit einem leeren Klammerpaar oder geschweiften Klammern (seit C++11) initialisiert wird;
4) wenn ein benanntes Objekt (automatisch, statisch oder thread-lokal) mit einem Initialisierer deklariert wird, der aus einem Paar geschweifter Klammern besteht.

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 T ein Klassentyp ohne Standardkonstruktor, aber mit einem Konstruktor ist, der ein std::initializer_list akzeptiert, wird Listeninitialisierung durchgeführt.

(seit C++11)

Die Auswirkungen der Wertinitialisierung sind:

  • Wenn T ein (möglicherweise cv-qualifizierter) Klassentyp ist:
  • Andernfalls, falls T ein 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

Siehe auch