问题
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?
回答1:
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.
回答2:
[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 typeT
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 ifT
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.
回答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).
回答4:
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.
来源:https://stackoverflow.com/questions/8092670/uninitialized-const