Standardkonstruktoren
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
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 |
(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 StandardkonstruktorDer implizit deklarierte oder explizit als Standard gesetzte Standardkonstruktor für die Klasse
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).
-
That keine virtuellen Memberfunktionen. -
That keine virtuellen Basisklassen.
|
(seit C++11) |
- Jede direkte Basis von
That einen trivialen Standardkonstruktor.
|
(bis C++26) |
|
(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 |