16

This compiles perfectly fine with the current MSVC compiler:

struct Foo
{
} const foo;

However, it fails to compile with the current g++ compiler:

error: uninitialized const 'foo' [-fpermissive]
note: 'const struct Foo' has no user-provided default constructor

If I provide a default constructor myself, it works:

struct Foo
{
    Foo() {}
} const foo;

Is this another case of MSVC being too permissive, or is g++ too strict here?

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • Duplicates: http://stackoverflow.com/questions/5335836/why-a-const-object-of-an-empty-class-cant-be-created http://stackoverflow.com/questions/7411515/why-does-c-require-a-user-provided-default-constructor-to-default-construct-a among others. – GManNickG Nov 11 '11 at 10:40
  • I cannot reproduce this on GCC 4.6.1, with any dialect option. It only works if I install a member variable (like `int a;`), and the error is much more accurate: `‘const struct Foo’ has no user-provided default constructor and the implicitly-defined constructor does not initialize ‘int Foo::a’` – Kerrek SB Nov 11 '11 at 10:45
  • @KerrekSB: All I do is `g++ foo.cpp`, and `g++ --version` prints `g++ (GCC) 4.6.1`. – fredoverflow Nov 11 '11 at 11:18
  • @FredOverflow: Sorry, I meant GCC 4.6.2. Updated recently. – Kerrek SB Nov 11 '11 at 11:20

4 Answers4

15

The C++03 Standard:

8.5 [dcl.init] paragraph 9

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor.

From the above the error in gcc seems to be perfectly valid.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 2
    Note: if you would like an explanation as to why the way C-style implicit zero initialization for structs doesn't work in C++, it's because C and C++ implemented const differently, C++ had `const` before C did. See [this chat transcript](https://chat.stackoverflow.com/rooms/116940/conversation/uninitialized-consts2) for more information. – jrh Nov 18 '18 at 20:44
5

[2003: 8.5/9]: If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a nonstatic object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.

And:

[n3290: 8.5/11]: If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2._ —end note_ ]

[n3290: 8.5/6]: To default-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
  • if T is an array type, each element is default-initialized;
  • otherwise, no initialization is performed.

If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.

So MSVC is more permissive here than both standards mandate.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3

I don't know the exact wording of the standard, but the error in g++ seems quite more sensible than the option of not saying anything. Consider this:

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

Not in the case of a user provided default constructor (even if it does nothing) the compiler will call that constructor and the object will be initialized (by whatever definition of initialized you have implemented in your constructor).

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
0

C++17 Update

C++17 adds some nuance to the requirement that const-qualified class types have a default constructor. The standard now defines the "const-default-constructable" concept:

7 To default-initialize an object of type T means:

(7.1) — If T is a (possibly cv-qualified) class type, constructors are considered. The applicable constructors are enumerated, and the best one for the initializer() is chosen through overload resolution. The constructor thus selected is called, with an empty argument list, to initialize the object.
(7.2) — If T is an array type, each element is default-initialized.
(7.3) — Otherwise, no initialization is performed.

A class type T is const-default-constructible if default-initialization of T would invoke a user-provided constructor of T (not inherited from a base class) or if

(7.4) — each direct non-variant non-static data member M of T has a default member initializer or, if M is of class type X (or array thereof), X is const-default-constructible,
(7.5) — if T is a union with at least one non-static data member, exactly one variant member has a default member initializer,
(7.6) — if T is not a union, for each anonymous union member with at least one non-static data member (if any), exactly one non-static data member has a default member initializer, and
(7.7) — each potentially constructed base class of T is const-default-constructible.

If a program calls for the default-initialization of an object of a const-qualified type T, T shall be a const-default-constructible class type or array thereof.

ThomasMcLeod
  • 7,603
  • 4
  • 42
  • 80