Причина полягає в тому, що якщо у класу немає визначеного користувачем конструктора, він може бути 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.
Зазначений користувачем конструктор - це один із способів зробити клас не-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 (або його масиву), об'єкт ініціалізується за замовчуванням; [...]
У ньому йдеться про клас, не підпадаючий для підключення ПДВ, можливо типів, що мають кваліфікацію cv . Тобто об'єкт, який не є POD, повинен бути ініціалізований за замовчуванням, якщо не вказаний ініціалізатор. А що ініціалізовано за замовчуванням ? Для не-POD, специфікація говорить (§ 8.5 / 5),
Під ініціалізацією за замовчуванням об'єкта типу T означає:
- якщо T - тип класу, який не є POD (п. 9), викликається конструктор за замовчуванням для T (ініціалізація неправильно формується, якщо T не має доступного конструктора за замовчуванням);
Він просто говорить про конструктор за замовчуванням T, незалежно від того, чи визначено його користувачем або створений компілятором, не має значення.
Якщо вам це зрозуміло, то зрозумійте, що говорить далі специфікація ((§ 8.5 / 9),
[...]; якщо об’єкт має const-тип, базовий тип класу повинен мати оголошений користувачем конструктор за замовчуванням.
Отже, з цього тексту випливає, що програма буде неправильно сформована, якщо об'єкт має тип 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 )