Неинициализированный const
Это компилируется отлично с помощью текущего компилятора MSVC:
struct Foo
{
} const foo;
Однако он не скомпилируется с текущим компилятором g++:
error: uninitialized const 'foo' [-fpermissive]
note: 'const struct Foo' has no user-provided default constructor
Если я сам создаю конструктор по умолчанию, он работает:
struct Foo
{
Foo() {}
} const foo;
Является ли это еще одним случаем, когда MSVC является слишком разрешимым или слишком строгим?
Ответы
Ответ 1
Стандарт С++ 03:
8.5 [dcl.init] пункт 9
Если для объекта не задан инициализатор, а объект имеет (возможно, cv-квалифицированный) тип класса не-POD (или его массив), объект должен быть инициализирован по умолчанию; если объект имеет тип const-type, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию.
Из вышесказанного ошибка в gcc представляется совершенно корректной.
Ответ 2
[2003: 8.5/9]:
Если для объекта не задан инициализатор, а объект имеет (возможно, cv-квалифицированный) тип класса не-POD (или массив), объект должен быть инициализирован по умолчанию; если объект имеет const-qual type, тип базового класса должен иметь объявленный пользователем конструктор по умолчанию. В противном случае, если инициализатор не установлен для объекта, не являющегося объектом, объекта и его подобъектов, если любой, имеют неопределенное начальное значение; , если объект или любой из его подобъекты имеют const-квалифицированный тип, программа плохо сформирована.
и
[n3290: 8.5/11]:
Если для объекта не задан инициализатор, объект инициализируется по умолчанию:, если инициализация отсутствует выполненный объект с автоматическим или динамическим временем хранения неопределенное значение. [Примечание: объекты со статическими или потоковыми хранилищами длительность нулевой инициализации, см. 3.6.2._ -end note_]
[n3290: 8.5/6]:
По умолчанию инициализировать объект типа T
означает:
- , если
T
является (возможно, cv-qualit) типом класса (раздел 9), вызывается конструктор по умолчанию для T (и инициализация плохо сформирована, если T
не имеет доступного конструктора по умолчанию) - if
T
- тип массива, каждый элемент инициализируется по умолчанию; - в противном случае инициализация не выполняется.
Если программа вызывает инициализацию по умолчанию объекта типа const-type T
, T
должен быть типом класса с предоставленным пользователем конструктором по умолчанию.
Итак, MSVC здесь более разрешительный, чем оба стандарта.
Ответ 3
Я не знаю точной формулировки стандарта, но ошибка в g++ кажется более разумной, чем возможность ничего не говорить. Рассмотрим это:
struct X {
int value;
};
const X constant; // constant.value is undefined
Не в случае предоставленного пользователем конструктора по умолчанию (даже если он ничего не делает) компилятор вызовет этот конструктор, и объект будет инициализирован (любым определением инициализации, которое вы внедрили в свой конструктор).