неинициализированный конст - PullRequest
16 голосов
/ 11 ноября 2011

Это прекрасно компилируется с текущим компилятором 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 слишком разрешительный или g ++ здесь слишком строг?

Ответы [ 4 ]

15 голосов
/ 11 ноября 2011

Стандарт C ++ 03:

8,5 [dcl.init] пункт 9

Если для объекта не указан инициализатор и объект относится к (возможно, cv-квалифицированному) не относящемуся к POD типу класса (или его массиву), объект должен инициализироваться по умолчанию; если объект имеет константный тип, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию.

Исходя из вышесказанного, ошибка в gcc представляется вполне допустимой.

5 голосов
/ 11 ноября 2011

[2003: 8.5/9]: Если для объекта не указан инициализатор, и объект имеет (возможно, cv-квалифицированный) тип класса не POD (или его массив), theобъект должен быть инициализирован по умолчанию;если объект имеет константный тип, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию.В противном случае, , если для нестатического объекта не указан инициализатор, объект и его подобъекты, если таковые имеются, имеют неопределенное начальное значение; если объект или какой-либо из его подобъектов имеют константный тип, программа является некорректной.

И:

[n3290: 8.5/11]: Если для объекта не указан инициализатор, объект инициализируется по умолчанию; если инициализация не выполняется, объект с автоматическим или динамическим сроком хранения имеет неопределенное значение.[ Примечание: Объекты со статической или длительностью хранения потока инициализируются нулями, см. 3.6.2._ — end end note_]

[n3290: 8.5/6]: К Инициализация по умолчанию объект типа T означает:

  • , если T является (возможно, cv-квалифицированным) типом класса (раздел 9), вызывается конструктор по умолчанию для T (иинициализация некорректна, если T не имеет доступного конструктора по умолчанию);
  • , если T является типом массива, каждый элемент инициализируется по умолчанию;
  • в противном случае, нетинициализация выполняется.

Если программа вызывает инициализацию по умолчанию для объекта типа с константой T, T должен быть типом класса с предоставленным пользователемконструктор по умолчанию.

Так что MSVC здесь более строгий, чем мандат обоих стандартов.

2 голосов
/ 11 ноября 2011

Я не знаю точную формулировку стандарта, но ошибка в g ++ кажется более разумной, чем возможность ничего не говорить. Учтите это:

struct X {
   int value;
};
const X constant; // constant.value is undefined

Не в случае предоставленного пользователем конструктора по умолчанию (даже если он ничего не делает), компилятор вызовет этот конструктор, и объект будет инициализирован (по любому определению инициализирован вы реализовали в своем конструкторе).

0 голосов
/ 23 октября 2018

C ++ 17 Обновление

C ++ 17 добавляет некоторый нюанс к требованию, чтобы типы классов с константой имели конструктор по умолчанию. Стандарт теперь определяет концепцию const-default-constructable:

7 К инициализация по умолчанию объект типа T означает:

(7.1) - Если T является (возможно, cv-квалифицированным) типом класса, рассматриваются конструкторы. Применимые конструкторы перечислены, и лучший выбор для инициализатора () выбирается через разрешение перегрузки. Выбранный таким образом конструктор вызывается с пустым списком аргументов для инициализации объект.
(7.2) - Если T является типом массива, каждый элемент инициализируется по умолчанию.
(7.3) - В противном случае инициализация не выполняется.

Тип класса T является const-default-конструируемым, если инициализация по умолчанию для T вызовет предоставленный пользователем конструктор T (не унаследованный от базового класса) или если

(7.4) - каждый прямой не вариантный нестатический элемент данных M из T имеет инициализатор элемента по умолчанию или, если M , имеет тип класса X (или их массив), X является const-default-constructible,
(7.5) - если T является объединением хотя бы с одним нестатическим элементом данных, то точно один вариантный элемент имеет инициализатор элемента по умолчанию,
(7.6) - если T не является объединением, для каждого анонимного члена объединения, имеющего хотя бы один элемент не статических данных (если есть), точно один элемент не статических данных имеет инициализатор элемента по умолчанию, и
(7.7) - каждый потенциально сконструированный базовый класс T является const-default-constructible.

Если программа вызывает инициализацию по умолчанию для объекта с квалифицированным константным типом T , T должен быть типом константного конструируемого класса или его массивом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...