Namespaces
Variants

Default constructors

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
Default constructor
Copy constructor
Move constructor (C++11)
Templates
Miscellaneous

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

Inhaltsverzeichnis

Syntax

class-name  ( parameter-list  (optional) ); (1)
class-name  ( parameter-list  (optional) ) function-body (2)
class-name  () = default; (3) (seit C++11)
class-name  ( parameter-list  (optional) ) = delete; (4) (seit C++11)
class-name  :: class-name  ( parameter-list  (optional) ) function-body (5)
class-name  :: class-name  () = default; (6) (seit C++11)
class-name - die Klasse, deren Standardkonstruktor deklariert wird
parameter-list - eine Parameterliste , in der alle Parameter (außer Parameter Packs ) (seit C++11) über Standardargumente verfügen
function-body - der Funktionsrumpf des Standardkonstruktors

Erklärung

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

Default-Konstruktoren werden während Default-Initialisierung und Wertinitialisierung aufgerufen.

Implizit deklarierter Standardkonstruktor

Wenn kein benutzerdeklarierter Konstruktor oder Konstruktortemplate für einen Klassentyp vorhanden ist, wird der Compiler implizit einen Standardkonstruktor als inline public Mitglied seiner Klasse deklarieren.

Der implizit deklarierte (oder bei seiner ersten Deklaration defaulted) Standardkonstruktor hat eine Ausnahmespezifikation, wie beschrieben in dynamische Ausnahmespezifikation (bis C++17) noexcept-Spezifikation (seit C++17) .

Implizit definierter Standardkonstruktor

Wenn der Konstruktor implizit deklariert ist (bis C++11) der implizit deklarierte oder explizit defaulted Standardkonstruktor nicht als gelöscht definiert ist (seit C++11) , wird er implizit durch den Compiler definiert, wenn odr-used oder needed for constant evaluation oder wenn er explizit nach seiner ersten Deklaration defaulted wird (seit C++11) .

Wenn ein Standardkonstruktor einer Union-ähnlichen Klasse T trivial ist, dann beginnt für jede Union U , die entweder T selbst oder eine anonyme Union-Komponente von T ist, der Standardkonstruktor von T die Lebensdauer des ersten Varianten-Mitglieds (falls vorhanden) von U , wenn dieses einen Implicit-Lifetime-Typ besitzt und nicht das aktive Mitglied seiner Union ist.

(seit C++26)

Ein (bis C++26) Andernfalls hat ein (seit C++26) implizit definierter Standardkonstruktor denselben Effekt wie ein benutzerdefinierter Konstruktor mit leerem Rumpf und leerer Initialisierungsliste. Das heißt, er ruft die Standardkonstruktoren der Basisklassen und der nicht-statischen Member dieser Klasse auf. Klassentypen mit einem leeren benutzerbereitgestellten Konstruktor können während der Wertinitialisierung anders behandelt werden als solche mit einem implizit definierten Standardkonstruktor.

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

Falls benutzerdefinierte Konstruktoren vorhanden sind, kann der Benutzer die automatische Generierung eines Standardkonstruktors durch den Compiler, der sonst implizit deklariert worden wäre, mit dem Schlüsselwort default erzwingen.

(seit C++11)


Gelöschter Standardkonstruktor

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

  • T hat ein nicht-statisches Datenelement vom Referenztyp ohne Default-Initialisierer.
  • T ist eine Nicht- Union -Klasse und (seit C++26) hat ein nicht-variantes, nicht-statisches, nicht- const-default-constructible Datenelement von const-qualifiziertem Typ (oder möglicherweise mehrdimensionalem Array davon) ohne Default-Member-Initialisierer.
  • T ist eine Union und alle ihre Varianten-Member sind von const-qualifiziertem Typ (oder möglicherweise mehrdimensionalem Array davon).
  • T ist eine Nicht-Union-Klasse und alle Member einer beliebigen anonymen Union sind von const-qualifiziertem Typ (oder möglicherweise mehrdimensionalem Array davon).
(bis C++26)
  • Gegeben einen Klassentyp M , T hat ein potenziell konstruiertes Subobjekt obj vom Typ M (oder möglicherweise mehrdimensionalem Array davon), und eine der folgenden Bedingungen ist erfüllt:
  • M hat einen Destruktor, der gelöscht oder für den Standardkonstruktor unzugänglich ist , und entweder obj ist nicht-variant oder obj hat einen Default-Member-Initialisierer (seit C++26) .
  • Alle folgenden Bedingungen sind erfüllt:
  • obj ist kein nicht-statisches Datenelement mit einem Default-Initialisierer.
  • obj ist kein Varianten-Member einer Union, bei der ein anderes nicht-statisches Datenelement einen Default-Initialisierer hat (bis C++26) .
  • Die Überladungsauflösung, angewendet um M 's Standardkonstruktor zu finden, ergibt keinen verwendbaren Kandidaten , oder im Fall von obj als Varianten-Member, wählt eine nicht-triviale Funktion (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 weiterhin mit dem Schlüsselwort delete unterbinden.

(seit C++11)

Trivialer Standardkonstruktor

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

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

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

Berechtigter Standardkonstruktor

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

(until C++11)

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

(since C++11)
(until C++20)

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

(since C++20)

Die Trivialität von qualifizierten Standardkonstruktoren bestimmt, ob die Klasse ein implicit-lifetime type ist, und ob die Klasse ein trivially copyable type ist.

Hinweise

Feature-Test-Makro Wert Std Feature
__cpp_trivial_union 202502L (C++26) Lockerung der Trivialitätsanforderungen für spezielle Memberfunktionen von Unions

Beispiel

struct A
{
    int x;
    A(int x = 1): x(x) {} // benutzerdefinierter Standardkonstruktor
};
struct B : A
{
    // B::B() ist implizit definiert, ruft A::A() auf
};
struct C
{
    A a;
    // C::C() ist implizit definiert, ruft A::A() auf
};
struct D : A
{
    D(int y) : A(y) {}
    // D::D() ist nicht deklariert, da ein anderer Konstruktor existiert
};
struct E : A
{
    E(int y) : A(y) {}
    E() = default; // explizit standardmäßig, ruft A::A() auf
};
struct F
{
    int& ref; // Referenzmitglied
    const int c; // konstantes Mitglied
    // F::F() ist implizit als gelöscht definiert
};
// benutzerdeklarierter Kopierkonstruktor (entweder benutzerbereitgestellt, gelöscht oder standardmäßig)
// verhindert die implizite Generierung eines Standardkonstruktors
struct G
{
    G(const G&) {}
    // G::G() ist implizit als gelöscht definiert
};
struct H
{
    H(const H&) = delete;
    // H::H() ist implizit als gelöscht definiert
};
struct I
{
    I(const I&) = default;
    // I::I() ist implizit als gelöscht definiert
};
int main()
{
    A a;
    B b;
    C c;
//  D d; // Kompilierungsfehler
    E e;
//  F f; // Kompilierungsfehler
//  G g; // Kompilierungsfehler
//  H h; // Kompilierungsfehler
//  I i; // Kompilierungsfehler
}

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 1353 C++11 die Bedingungen, unter denen implizit deklarierte Standardkonstruktoren
als gelöscht definiert sind, berücksichtigten keine mehrdimensionalen Array-Typen
diese Typen berücksichtigen
CWG 2084 C++11 Standard-Member-Initialisierer hatten keinen Einfluss darauf, ob
ein standardmäßiger Standardkonstruktor einer Union gelöscht ist
sie verhindern, dass der standardmäßige Standard-
konstruktor gelöscht wird
CWG 2595 C++20 ein Standardkonstruktor war nicht berechtigt, wenn es
einen anderen Standardkonstruktor gibt, der stärker eingeschränkt ist
aber seine zugehörigen Constraints nicht erfüllt
er kann in diesem Fall berechtigt sein
CWG 2871 C++98 ein Standardkonstruktor würde implizit deklariert werden
selbst wenn ein benutzerdeklarierter Konstruktortemplate vorhanden ist
keine implizite Deklaration
in diesem Fall

Siehe auch