Namensräume
Varianten
Aktionen

Wertinitialisierung

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Dies ist die Initialisierung, die durchgeführt wird, wenn ein Objekt mit einem leeren Initialisierer konstruiert wird.

Inhalt

[bearbeiten] Syntax

T () (1)
new T () (2)
Klasse::Klasse(...) : Mitglied () { ... } (3)
T objekt {}; (4) (seit C++11)
T {} (5) (seit C++11)
new T {} (6) (seit C++11)
Klasse::Klasse(...) : Mitglied {} { ... } (7) (seit C++11)

[bearbeiten] Erklärung

Wertinitialisierung wird in diesen Situationen durchgeführt

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

In allen Fällen, wenn das leere geschweifte Klammerpaar {} verwendet wird und T ein Aggregattyp ist, wird stattdessen Aggregatinitialisierung anstelle von Wertinitialisierung durchgeführt.

Wenn T ein Klassentyp ist, der keinen Standardkonstruktor, aber einen Konstruktor hat, der std::initializer_list als Parameter nimmt, wird Listeninitialisierung durchgeführt.

(seit C++11)

Die Auswirkungen der Wertinitialisierung sind

  • Wenn T ein (möglicherweise cv-qualifizierter) Klassentyp ist
  • Andernfalls, wenn T ein Arraytyp ist, wird jedes Element des Arrays wertinitialisiert.
  • Andernfalls wird das Objekt nullinitialisiert.

[bearbeiten] Hinweise

Die Syntax T objekt(); initialisiert kein Objekt; sie deklariert eine Funktion, die keine Argumente annimmt und T zurückgibt. Die Art, ein benanntes Objekt vor C++11 wertzuinitialisieren, war T objekt = T();, was ein temporäres Objekt wertinitialisiert und dann das Objekt durch Kopierinitialisierung initialisiert: Die meisten Compiler optimieren die Kopie in diesem Fall weg.

Referenzen können nicht wertinitialisiert werden.

Wie in Funktionsstil-Cast beschrieben, ist die Syntax T() (1) verboten, wenn T einen Arraytyp benennt, während T{} (5) erlaubt ist.

Alle Standardcontainer (std::vector, std::list, etc.) wertinitialisieren ihre Elemente, wenn sie mit einem einzigen size_type-Argument konstruiert werden oder wenn sie durch einen Aufruf von resize() vergrößert werden, es sei denn, ihr Allocator passt das Verhalten von construct an.

[bearbeiten] Beispiel

#include <cassert>
#include <iostream>
#include <string>
#include <vector>
 
struct T1
{
    int mem1;
    std::string mem2;
    virtual void foo() {} // make sure T1 is not an aggregate
}; // implicit default constructor
 
struct T2
{
    int mem1;
    std::string mem2;
    T2(const T2&) {} // user-provided copy constructor
};                   // no default constructor
 
struct T3
{
    int mem1;
    std::string mem2;
    T3() {} // user-provided default constructor
};
 
std::string s{}; // class => default-initialization, the value is ""
 
int main()
{
    int n{};                // scalar => zero-initialization, the value is 0
    assert(n == 0);
    double f = double();    // scalar => zero-initialization, the value is 0.0
    assert(f == 0.0);
    int* a = new int[10](); // array => value-initialization of each element
    assert(a[9] == 0);      //          the value of each element is 0
    T1 t1{};                // class with implicit default constructor =>
    assert(t1.mem1 == 0);   //     t1.mem1 is zero-initialized, the value is 0
    assert(t1.mem2 == "");  //     t1.mem2 is default-initialized, the value is ""
//  T2 t2{};                // error: class with no default constructor
    T3 t3{};                // class with user-provided default constructor =>
    std::cout << t3.mem1;   //     t3.mem1 is default-initialized to indeterminate value
    assert(t3.mem2 == "");  //     t3.mem2 is default-initialized, the value is ""
    std::vector<int> v(3);  // value-initialization of each element
    assert(v[2] == 0);      // the value of each element is 0
    std::cout << '\n';
    delete[] a;
}

Mögliche Ausgabe

42

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 178 C++98 es gab keine Wertinitialisierung; ein leerer Initialisierer rief die Standard-
Initialisierung auf (obwohl new T() auch Nullinitialisierung durchführt)
leerer Initialisierer ruft
Wertinitialisierung auf
CWG 543 C++98 die Wertinitialisierung für ein Klassenobjekt ohne
benutzerbereitgestellte Konstruktoren war äquivalent zur Wert-
Initialisierung jedes Unterobjekts (das keine Null-
Initialisierung eines Mitglieds mit einem benutzerbereitgestellten Standardkonstruktor erfordert)
Nullinitialisiert
das gesamte Objekt,
ruft dann den
Standardkonstruktor
CWG 1301 C++11 Wertinitialisierung von Unions mit gelöschten
Standardkonstruktoren führte zu Nullinitialisierung
sie sind
Standardinitialisiert
CWG 1368 C++98 jeder benutzerbereitgestellte Konstruktor bewirkte,
dass die Nullinitialisierung übersprungen wurde
nur ein benutzerbereitgestellter
Standardkonstruktor
überspringt die Nullinitialisierung
CWG 1502 C++11 die Wertinitialisierung einer Union ohne benutzerbereitgestellten
Standardkonstruktor nullinitialisierte nur das
Objekt, trotz standardmäßiger Mitgliederinitialisierer
führt die Standard-
Initialisierung nach
Nullinitialisierung durch
CWG 1507 C++98 die Wertinitialisierung für ein Klassenobjekt ohne
benutzerbereitgestellte Konstruktoren überprüften nicht die Gültigkeit
des Standardkonstruktors, wenn letzterer trivial ist
die Gültigkeit des trivialen
Standardkonstruktor
wird überprüft
CWG 2820 C++98 die Standardinitialisierung nach der Null-
Initialisierung erforderte einen nicht-trivialen Konstruktor
nicht erforderlich.
CWG 2859 C++98 die Wertinitialisierung für ein Klassenobjekt könnte
eine Nullinitialisierung beinhalten, auch wenn die Standard-
Initialisierung nicht tatsächlich einen benutzerbereitgestellten Konstruktor auswählt
es gibt keine
Nullinitialisierung durch
in diesem Fall

[bearbeiten] Siehe auch