Namensräume
Varianten
Aktionen

Standardkonstruktoren

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
Standardkonstruktor
Kopierkonstruktor
Move-Konstruktor (C++11)
Templates
Sonstiges
 
 

Ein Standardkonstruktor ist ein Konstruktor, der ohne Argumente aufgerufen werden kann.

Inhalt

[bearbeiten] Syntax

klassenname (parameterliste (optional)); (1)
klassenname (parameterliste (optional)) funktionsrumpf (2)
klassenname () = default; (3) (seit C++11)
klassenname (parameterliste (optional)) = delete; (4) (seit C++11)
klassenname ::klassenname (parameterliste (optional)) funktionsrumpf (5)
klassenname ::klassenname () = default; (6) (seit C++11)
Klassenname - die Klasse, deren Standardkonstruktor deklariert wird
parameter-liste - eine Parameterliste, bei der alle Parameter (außer Parameter-Packs)(seit C++11) Standardargumente haben
function-body - der Funktionsrumpf des Standardkonstruktors

[bearbeiten] Erklärung

1) Deklaration eines Standardkonstruktors innerhalb der Klassendefinition.
2-4) Definition eines Standardkonstruktors innerhalb der Klassendefinition.
3) Der Standardkonstruktor ist explizit als Standardwert gesetzt.
4) Der Standardkonstruktor ist gelöscht.
5,6) Definition eines Standardkonstruktors außerhalb der Klassendefinition (die Klasse muss eine Deklaration (1) enthalten).
6) Der Standardkonstruktor ist explizit als Standardwert gesetzt.

Standardkonstruktoren werden bei Standardinitialisierungen und Wertinitialisierungen aufgerufen.

[bearbeiten] Implizit deklarierter Standardkonstruktor

Wenn für einen Klassentyp kein benutzerdefinierter Konstruktor oder Konstruktor-Template vorhanden ist, deklariert der Compiler implizit einen Standardkonstruktor als inline public Mitglied seiner Klasse.

Der implizit deklarierte (oder bei seiner ersten Deklaration als Standard gesetzte) Standardkonstruktor hat eine Ausnahme-Spezifikation, wie in der dynamischen Ausnahme-Spezifikation(bis C++17) noexcept-Spezifikation(seit C++17) beschrieben.

[bearbeiten] Implizit definierter Standardkonstruktor

Wenn der Konstruktor implizit deklariert ist(bis C++11)der implizit deklarierte oder explizit als Standard gesetzte Standardkonstruktor nicht als gelöscht definiert ist(seit C++11), wird er vom Compiler implizit definiert, wenn er ODR-benutzt wird oder für die konstante Auswertung benötigt wird(seit C++11).

Wenn ein Standardkonstruktor einer Union-ähnlichen Klasse T trivial ist, dann für jede Union U, die entweder T oder ein anonymes Union-Mitglied von T ist, wenn das erste Variantenmitglied (falls vorhanden) von U einen implizit lebenden Typ hat, beginnt der Standardkonstruktor von T die Lebensdauer dieses Mitglieds, wenn es nicht das aktive Mitglied seiner Union ist.

(seit C++26)

Ein(bis C++26)Andernfalls hat ein(seit C++26) implizit definierter Standardkonstruktor die gleiche Wirkung wie ein benutzerdefinierter Konstruktor mit leerem Rumpf und leerer Initialisierungsliste. Das heißt, er ruft die Standardkonstruktoren der Basen und der nicht-statischen Mitglieder dieser Klasse auf. Klassen mit einem leeren, benutzerdefinierten Konstruktor können sich bei der Wertinitialisierung von denen mit einem implizit definierten Standardkonstruktor unterscheiden.

Wenn dies die Anforderungen an einen constexpr Konstruktor(bis C++23)constexpr Funktion(seit C++23) erfüllt, ist der generierte Konstruktor constexpr.

Wenn einige benutzerdefinierte Konstruktoren vorhanden sind, kann der Benutzer die automatische Generierung eines Standardkonstruktors durch den Compiler, der andernfalls implizit deklariert würde, mit dem Schlüsselwort default erzwingen.

(seit C++11)


Gelöschter Standardkonstruktor

Der implizit deklarierte oder explizit als Standard gesetzte Standardkonstruktor für die Klasse T wird als gelöscht definiert, wenn eine der folgenden Bedingungen erfüllt ist

  • T hat ein nicht-statisches Datenelement vom Referenztyp ohne Standardinitialisierer.
  • T ist eine nicht-Union-Klasse und(seit C++26) hat ein nicht-variantes nicht-statisches, nicht- standardkonstruierbares Datenelement vom const-qualifizierten Typ (oder möglicherweise ein mehrdimensionales Array davon) ohne Standardmitgliedinitialisierer.
  • T ist eine Union und alle ihre Variantenmitglieder sind vom const-qualifizierten Typ (oder möglicherweise ein mehrdimensionales Array davon).
  • T ist eine Nicht-Union-Klasse und alle Mitglieder einer anonymen Union sind vom const-qualifizierten Typ (oder möglicherweise ein mehrdimensionales Array davon).
(bis C++26)
  • M hat einen Destruktor, der gelöscht oder vom Standardkonstruktor aus nicht zugänglich ist, und entweder ist obj nicht-variant oder obj hat einen Standardmitgliedinitialisierer(seit C++26).
  • Alle folgenden Bedingungen sind erfüllt
  • obj ist kein nicht-statisches Datenelement mit einem Standardinitialisierer.
  • obj ist kein Variantenmitgliedeiner Union, bei der ein anderes nicht-statisches Datenelement einen Standardinitialisierer hat(bis C++26).
  • Die Überladungsauflösung, die angewendet wird, um den Standardkonstruktor von M zu finden, führt nicht zu einem nutzbaren Kandidaten, oder im Falle von obj als Variantenmitglied wird eine nicht-triviale Funktion ausgewählt(bis C++26).

Wenn keine benutzerdefinierten Konstruktoren vorhanden sind und der implizit deklarierte Standardkonstruktor nicht trivial ist, kann der Benutzer die automatische Generierung eines implizit definierten Standardkonstruktors durch den Compiler mit dem Schlüsselwort delete immer noch unterbinden.

(seit C++11)

[bearbeiten] Trivialer Standardkonstruktor

Der Standardkonstruktor für Klasse T ist trivial, wenn alle folgenden Bedingungen erfüllt sind

  • Der Konstruktor ist implizit deklariert(bis C++11)nicht benutzerdefiniert(seit C++11).
  • T hat keine virtuellen Memberfunktionen.
  • T hat keine virtuellen Basisklassen.
  • T hat keine nicht-statischen Mitglieder mit Standardinitialisierern.
(seit C++11)
  • Jede direkte Basis von T hat einen trivialen Standardkonstruktor.
  • Jedes nicht-statische Mitglied vom Klassentyp (oder ein Array davon) hat einen trivialen Standardkonstruktor.
(bis C++26)
  • Entweder ist T eine Union, oder jedes nicht-variante nicht-statische Mitglied vom Klassentyp (oder ein Array davon) hat einen trivialen Standardkonstruktor.
(seit C++26)

Ein trivialer Standardkonstruktor ist ein Konstruktor, der keine Aktion ausführt. Alle mit C kompatiblen Datentypen (POD-Typen) sind trivial standardkonstruierbar.

[bearbeiten] Berechtigter Standardkonstruktor

Ein Standardkonstruktor ist berechtigt, wenn er entweder benutzerdeklariert oder sowohl implizit deklariert als auch definierbar ist.

(bis C++11)

Ein Standardkonstruktor ist berechtigt, wenn er nicht gelöscht ist.

(seit C++11)
(bis C++20)

Ein Standardkonstruktor ist berechtigt, wenn alle folgenden Bedingungen erfüllt sind

(seit C++20)

Die Trivialität von berechtigten Standardkonstruktoren bestimmt, ob die Klasse ein implizit lebender Typ ist und ob die Klasse ein trivial kopierbarer Typ ist.

[bearbeiten] Anmerkungen

Feature-Testmakro Wert Std Feature
__cpp_trivial_union 202502L (C++26) Lockerung der trivialen Anforderungen für spezielle Memberfunktionen von Unions

[bearbeiten] Beispiel

struct A
{
    int x;
    A(int x = 1): x(x) {} // user-defined default constructor
};
 
struct B : A
{
    // B::B() is implicitly-defined, calls A::A()
};
 
struct C
{
    A a;
    // C::C() is implicitly-defined, calls A::A()
};
 
struct D : A
{
    D(int y) : A(y) {}
    // D::D() is not declared because another constructor exists
};
 
struct E : A
{
    E(int y) : A(y) {}
    E() = default; // explicitly defaulted, calls A::A()
};
 
struct F
{
    int& ref; // reference member
    const int c; // const member
    // F::F() is implicitly defined as deleted
};
 
// user declared copy constructor (either user-provided, deleted or defaulted)
// prevents the implicit generation of a default constructor
 
struct G
{
    G(const G&) {}
    // G::G() is implicitly defined as deleted
};
 
struct H
{
    H(const H&) = delete;
    // H::H() is implicitly defined as deleted
};
 
struct I
{
    I(const I&) = default;
    // I::I() is implicitly defined as deleted
};
 
int main()
{
    A a;
    B b;
    C c;
//  D d; // compile error
    E e;
//  F f; // compile error
//  G g; // compile error
//  H h; // compile error
//  I i; // compile error
}

[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 1353 C++11 die Bedingungen, unter denen implizit deklarierte Standardkonstruktoren
als gelöscht definiert wurden, berücksichtigten keine mehrdimensionalen Array-Typen
diese Typen berücksichtigen
CWG 2084 C++11 Standardmitgliedinitialisierer hatten keine Auswirkung darauf, ob
ein als Standard gesetzter Standardkonstruktor einer Union gelöscht wird
sie verhindern, dass der als Standard gesetzte
Standardkonstruktor gelöscht wird
CWG 2595 C++20 ein Standardkonstruktor war nicht berechtigt, wenn es
einen anderen Standardkonstruktor gibt, der eingehender eingeschränkt ist
aber seine zugehörigen Constraints nicht erfüllte
er kann in diesem Fall berechtigt sein
CWG 2871 C++98 ein Standardkonstruktor würde implizit deklariert werden
auch wenn ein benutzerdefinierter Konstruktor-Template vorhanden ist
keine implizite Deklaration
in diesem Fall

[bearbeiten] Siehe auch