Я определил POD, который я планирую использовать в качестве неизменяемого хранилища данных. Чтобы добиться этого, я определил его членов как const
, и я ожидаю инициализировать значение-инициализацию экземпляров (и в некоторых случаях нуль-инициализировать). Рассмотрим следующий код:
struct Foo
{
const int value;
};
int main()
{
Foo foo{ };
return 0;
}
Когда я пытаюсь выполнить инициализацию этого POD с нулевой инициализацией, я получаю ошибку компилятора в Visual Studio (C3852) из-за квалификатора const
на Foo::value
. Если я удалю классификатор, код компилируется нормально.
Точное сообщение об ошибке:
ошибка C3852: 'Foo:: value' с типом 'const int': инициализация агрегата не может инициализировать этот член const не могут быть инициализированы по умолчанию, если их тип не имеет пользовательского конструктора по умолчанию
В соответствии со стандартом (проект n3337), §8.5/5 (нулевая инициализация):
Для нулевой инициализации объекта или ссылки типа T означает:
- если T - скалярный тип (3.9), объект устанавливается в значение 0 (ноль), взятое как интегральное постоянное выражение, преобразован в T;
- если T является (возможно, cv-квалифицированным) классом неединичного класса, каждый нестатический член данных и каждый базовый класс подобъект инициализируется нулем, а заполнение инициализируется нулевыми битами;
- если T является (возможно, cv-квалифицированным) объединенным типом, объекты сначала нестатического именованного элемента данных ноль инициализируются и заполнение инициализируется нулевыми битами;
- если T - тип массива, каждый элемент инициализируется нулем;
- если T является ссылочным типом, инициализация не выполняется.
и §8.5/6 (инициализация по умолчанию):
Для инициализации объекта типа T по умолчанию:
- если T является (возможно, cv-квалифицированным) классом типа (раздел 9), вызывается конструктор по умолчанию для T (и инициализация плохо сформирована, если T не имеет доступного конструктора по умолчанию);
- если T - тип массива, каждый элемент инициализируется по умолчанию;
- в противном случае инициализация не выполняется. Если программа требует инициализации по умолчанию объекта типа, определенного с помощью const, T должен быть классом типа с предоставленным пользователем конструктором по умолчанию.
и §8.5/7 (инициализация значения):
Для инициализации объекта типа типа T означает:
- если T является (возможно, cv-квалифицированным) классом типа (раздел 9) с предоставленным пользователем конструктором (12.1), то вызывается конструктор по умолчанию для T (и инициализация плохо сформирована, если T не имеет доступного значения по умолчанию Конструктор);
- если T является (возможно, cv-квалифицированным) классом типа non-union без предоставленного пользователем конструктора, тогда объект инициализируется нулем и, если Ts неявно объявленный конструктор по умолчанию является нетривиальным, этот конструктор называется.
- если T - тип массива, то каждый элемент инициализируется значением;
- в противном случае объект инициализируется нулем.
Мое чтение стандарта заставляет меня поверить, что мой POD должен быть инициализирован нулем; не инициализируется по умолчанию. Я неправильно понимаю процесс инициализации, описанный в стандарте?
РЕДАКТИРОВАТЬ: Учитывая детали, представленные в принятом ответе и связанных комментариях, это выглядит как потенциальная ошибка в реализации VS (то есть реализация может основываться на устаревшей версии стандарта), Я создал билет Microsoft Connect для отслеживания этого, который можно найти здесь: