Причина в том, что если у класса нет определяемого пользователем конструктора, то он может быть POD, а класс POD не инициализируется по умолчанию. Итак, если вы объявляете неинициализированный константный объект POD, какой в этом смысл? Поэтому я думаю, что Стандарт применяет это правило, чтобы объект действительно мог быть полезным.
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!
Но если вы сделаете класс не-POD:
struct nonPOD_A
{
nonPOD_A() {} //this makes non-POD
};
nonPOD_A a1; //initialized
const nonPOD_A a2; //initialized
Обратите внимание на разницу между POD и не-POD.
Пользовательский конструктор - это один из способов сделать класс не-POD. Есть несколько способов сделать это.
struct nonPOD_B
{
virtual void f() {} //virtual function make it non-POD
};
nonPOD_B b1; //initialized
const nonPOD_B b2; //initialized
Обратите внимание, что nonPOD_B не определяет пользовательский конструктор. Скомпилируйте это. Он скомпилирует:
И прокомментируйте виртуальную функцию, тогда она выдаст ошибку, как и ожидалось:
Ну, я думаю, вы неправильно поняли отрывок. Сначала он говорит следующее (§8.5 / 9):
Если для объекта не указан инициализатор, и объект относится к типу ( возможно, cv-квалификационному) не-POD (или его массиву), объект должен быть инициализирован по умолчанию; [...]
Он говорит о не-POD-классе, возможно, о типе с квалификацией cv . То есть объект, не относящийся к POD, должен быть инициализирован по умолчанию, если не указан инициализатор. А что инициализировано по умолчанию ? Для не-POD спецификация говорит (§8.5 / 5),
Инициализация по умолчанию объекта типа T означает:
- если T не относится к типу класса POD (пункт 9), вызывается конструктор по умолчанию для T (и инициализация плохо сформирована, если T не имеет доступного конструктора по умолчанию);
Он просто говорит о конструкторе по умолчанию для T, независимо от того, не имеет значения его определяемый пользователем или созданный компилятором.
Если вы понимаете это, тогда поймите, что говорит спецификация дальше ((§8.5 / 9),
[...]; если объект имеет тип, определяемый константой, базовый тип класса должен иметь конструктор по умолчанию, объявленный пользователем.
Таким образом, этот текст подразумевает, что программа будет неправильно сформирована, если объект имеет тип POD, квалифицированный как const , и не указан инициализатор (поскольку POD не инициализируются по умолчанию):
POD p1; //uninitialized - can be useful - hence allowed
const POD p2; //uninitialized - never useful - hence not allowed - error
Между прочим, он компилируется нормально , потому что он не POD и может быть инициализирован по умолчанию .
a, но gcc-4.3.4 принимает ее, даже когда вы это делаете (см. Ideone.com/uHvFS )