Der Grund dafür ist, dass die Klasse, wenn sie keinen benutzerdefinierten Konstruktor hat, POD sein kann und die POD-Klasse nicht standardmäßig initialisiert wird. Wenn Sie also ein nicht initialisiertes const-Objekt von POD deklarieren, welchen Nutzen hat es dann? Daher denke ich, dass der Standard diese Regel erzwingt, damit das Objekt tatsächlich nützlich sein kann.
struct POD
{
int i;
};
POD p1; //uninitialized - but don't worry we can assign some value later on!
p1.i = 10; //assign some value later on!
POD p2 = POD(); //initialized
const POD p3 = POD(); //initialized
const POD p4; //uninitialized - error - as we cannot change it later on!
Aber wenn Sie die Klasse zu einem Nicht-POD machen:
struct nonPOD_A
{
nonPOD_A() {} //this makes non-POD
};
nonPOD_A a1; //initialized
const nonPOD_A a2; //initialized
Beachten Sie den Unterschied zwischen POD und Nicht-POD.
Der benutzerdefinierte Konstruktor ist eine Möglichkeit, die Klasse nicht POD zu machen. Es gibt verschiedene Möglichkeiten, dies zu tun.
struct nonPOD_B
{
virtual void f() {} //virtual function make it non-POD
};
nonPOD_B b1; //initialized
const nonPOD_B b2; //initialized
Beachten Sie, dass nonPOD_B keinen benutzerdefinierten Konstruktor definiert. Kompiliere es. Es wird kompiliert:
Und kommentieren Sie die virtuelle Funktion, dann gibt es wie erwartet Fehler:
Nun, ich denke, Sie haben die Passage falsch verstanden. Es sagt zuerst dies (§8.5 / 9):
Wenn für ein Objekt kein Initialisierer angegeben ist und das Objekt vom (möglicherweise lebenslaufqualifizierten) Nicht-POD-Klassentyp (oder einem Array davon) ist, muss das Objekt standardmäßig initialisiert werden. [...]
Es handelt sich um einen möglicherweise nicht lebenslaufqualifizierten Typ ohne POD-Klasse . Das heißt, das Nicht-POD-Objekt wird standardmäßig initialisiert, wenn kein Initialisierer angegeben ist. Und was ist standardmäßig initialisiert ? Für Nicht-POD heißt es in der Spezifikation (§8.5 / 5):
Die Standardinitialisierung eines Objekts vom Typ T bedeutet:
- Wenn T ein Nicht-POD-Klassentyp ist (Abschnitt 9), wird der Standardkonstruktor für T aufgerufen (und die Initialisierung ist fehlerhaft, wenn T keinen zugänglichen Standardkonstruktor hat);
Es geht einfach um den Standardkonstruktor von T, unabhängig davon, ob sein benutzerdefinierter oder vom Compiler generierter Konstruktor irrelevant ist.
Wenn Sie sich darüber im Klaren sind, verstehen Sie, was in der Spezifikation als nächstes steht ((§8.5 / 9),
[...]; Wenn das Objekt vom Typ const-qualifiziert ist, muss der zugrunde liegende Klassentyp einen vom Benutzer deklarierten Standardkonstruktor haben.
Dieser Text impliziert also, dass das Programm fehlerhaft ist, wenn das Objekt vom Typ POD mit konstanter Qualifikation ist und kein Initialisierer angegeben ist (da POD nicht standardmäßig initialisiert sind):
POD p1; //uninitialized - can be useful - hence allowed
const POD p2; //uninitialized - never useful - hence not allowed - error
Übrigens wird dies gut kompiliert , da es kein POD ist und standardmäßig initialisiert werden kann .
a
, aber gcc-4.3.4 akzeptiert sie auch dann, wenn Sie dies tun (siehe ideone.com/uHvFS ).