Powodem jest to, że jeśli klasa nie ma konstruktora zdefiniowanego przez użytkownika, może to być POD, a klasa POD nie jest domyślnie inicjowana. Więc jeśli zadeklarujesz stały obiekt POD, który jest niezainicjalizowany, po co z tego? Myślę więc, że standard wymusza tę zasadę, aby obiekt faktycznie był użyteczny.
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!
Ale jeśli ustawisz klasę jako inną niż POD:
struct nonPOD_A
{
nonPOD_A() {} //this makes non-POD
};
nonPOD_A a1; //initialized
const nonPOD_A a2; //initialized
Zwróć uwagę na różnicę między POD i bez POD.
Konstruktor zdefiniowany przez użytkownika jest jednym ze sposobów uczynienia klasy inną niż POD. Możesz to zrobić na kilka sposobów.
struct nonPOD_B
{
virtual void f() {} //virtual function make it non-POD
};
nonPOD_B b1; //initialized
const nonPOD_B b2; //initialized
Zauważ, że nonPOD_B nie ma zdefiniowanego konstruktora zdefiniowanego przez użytkownika. Skompiluj to. Skompiluje:
I skomentuj funkcję wirtualną, a następnie zgodnie z oczekiwaniami podaje błąd:
Myślę, że źle zrozumiałeś ten fragment. Najpierw mówi to (§ 8.5 / 9):
Jeśli dla obiektu nie określono inicjatora, a obiekt jest (prawdopodobnie kwalifikowany przez cv) typem innym niż POD (lub jego tablicą), obiekt powinien zostać zainicjowany domyślnie; […]
Mówi o typie bez klasy POD, który może kwalifikować się jako CV . Oznacza to, że obiekt inny niż POD powinien być inicjalizowany domyślnie, jeśli nie określono inicjatora. A co to jest inicjalizacja domyślna ? W przypadku braku POD, specyfikacja mówi (§8.5 / 5),
Domyślne zainicjowanie obiektu typu T oznacza:
- jeśli T jest typem klasy innym niż POD (klauzula 9), wywoływany jest domyślny konstruktor dla T (a inicjalizacja jest źle sformułowana, jeśli T nie ma dostępnego domyślnego konstruktora);
Po prostu mówi o domyślnym konstruktorze T, niezależnie od tego, czy jego zdefiniowany przez użytkownika, czy wygenerowany przez kompilator jest nieistotny.
Jeśli masz jasność co do tego, zrozum, co mówi dalej specyfikacja ((§8.5 / 9),
[...]; jeśli obiekt jest typu const-qualified, typ klasy bazowej powinien mieć domyślnego konstruktora zadeklarowanego przez użytkownika.
Tak więc ten tekst sugeruje, że program będzie źle sformułowany, jeśli obiekt jest typu POD o stałej kwalifikacji i nie określono inicjatora (ponieważ POD nie są domyślnie zainicjowane):
POD p1; //uninitialized - can be useful - hence allowed
const POD p2; //uninitialized - never useful - hence not allowed - error
Nawiasem mówiąc, kompiluje się dobrze , ponieważ nie jest to POD i może być inicjalizowany domyślnie .
a, ale gcc-4.3.4 akceptuje to nawet wtedy, gdy to zrobisz (patrz ideone.com/uHvFS )