Die Antworten von Angew und jaggedSpire sind ausgezeichnet und gelten fürc ++ 11. Undc ++ 14. Undc ++ 17.
In c ++ 20Die Dinge ändern sich ein wenig und das Beispiel im OP wird nicht mehr kompiliert:
class C {
C() = default;
};
C p; // always error
auto q = C(); // always error
C r{}; // ok on C++11 thru C++17, error on C++20
auto s = C{}; // ok on C++11 thru C++17, error on C++20
Wie aus den beiden Antworten hervorgeht, funktionieren die beiden letztgenannten Deklarationen, weil C
es sich um ein Aggregat handelt und es sich um eine Aggregatinitialisierung handelt. Aufgrund von P1008 (anhand eines motivierenden Beispiels, das sich nicht allzu sehr vom OP unterscheidet) ändert sich die Definition der aggregierten Änderungen in C ++ 20 von [dcl.init.aggr] / 1 :
Ein Aggregat ist ein Array oder eine Klasse ([Klasse]) mit
- keine vom Benutzer deklarierten oder geerbten Konstruktoren ([class.ctor]),
- keine privaten oder geschützten direkten nicht statischen Datenelemente ([class.access]),
- keine virtuellen Funktionen ([class.virtual]) und
- Keine virtuellen, privaten oder geschützten Basisklassen ([class.mi]).
Hervorhebung von mir. Jetzt sind keine vom Benutzer deklarierten Konstruktoren mehr erforderlich , während es früher (wie beide Benutzer in ihren Antworten zitieren und historisch für C ++ 11 , C ++ 14 und C ++ 17 angezeigt werden können ) keine vom Benutzer bereitgestellten Konstruktoren war . Der Standardkonstruktor für C
ist vom Benutzer deklariert, aber nicht vom Benutzer bereitgestellt und ist daher in C ++ 20 kein Aggregat mehr.
Hier ist ein weiteres anschauliches Beispiel für aggregierte Änderungen:
class A { protected: A() { }; };
struct B : A { B() = default; };
auto x = B{};
B
war kein Aggregat in C ++ 11 oder C ++ 14, da es eine Basisklasse hat. Als Ergebnis B{}
ruft nur den Standard - Konstruktor ( vom Benutzer deklariert , aber nicht vom Benutzer zur Verfügung gestellt), der Zugriff hat A
‚s geschützten Standardkonstruktor.
In C ++ 17 wurden als Ergebnis von P0017 Aggregate erweitert, um Basisklassen zu ermöglichen. B
ist ein Aggregat in C ++ 17, dh es B{}
handelt sich um eine Aggregatinitialisierung, bei der alle Unterobjekte - einschließlich des A
Unterobjekts - initialisiert werden müssen . Da A
der Standardkonstruktor jedoch geschützt ist, haben wir keinen Zugriff darauf, sodass diese Initialisierung fehlerhaft ist.
In C ++ 20 ist der vom B
Benutzer deklarierte Konstruktor aufgrund des vom Benutzer deklarierten Konstruktors wieder kein Aggregat B{}
mehr. Daher wird wieder der Standardkonstruktor aufgerufen, und dies ist wiederum eine wohlgeformte Initialisierung.
C c{};
aggregierte Initialisierung nicht so, dass kein Konstruktor aufgerufen wird?