C++ 未初始化常量

C++ 未初始化常量,c++,visual-c++,g++,constants,default-constructor,C++,Visual C++,G++,Constants,Default Constructor,使用当前的MSVC编译器,这种编译非常好: struct Foo { } const foo; error: uninitialized const 'foo' [-fpermissive] note: 'const struct Foo' has no user-provided default constructor 但是,它无法使用当前的g++编译器进行编译: struct Foo { } const foo; error: uninitialized const 'foo' [-f

使用当前的MSVC编译器,这种编译非常好:

struct Foo
{
} const foo;
error: uninitialized const 'foo' [-fpermissive]
note: 'const struct Foo' has no user-provided default constructor
但是,它无法使用当前的g++编译器进行编译:

struct Foo
{
} const foo;
error: uninitialized const 'foo' [-fpermissive]
note: 'const struct Foo' has no user-provided default constructor
如果我自己提供一个默认构造函数,它可以工作:

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

这是MSVC过于宽容的另一种情况,还是g++在这里过于严格?

我不知道标准的确切措辞,但g++中的错误似乎比什么都不说的选项更明智。考虑这一点:

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

如果是用户提供的默认构造函数(即使它什么也不做),编译器将调用该构造函数,并且对象将被初始化(通过在构造函数中实现的初始化的任何定义)。

C++03标准:

8.5[dcl.init]第9段

如果没有为对象指定初始值设定项,并且该对象是(可能是cv限定的)非POD类类型(或其数组),则该对象应默认初始化;如果对象是const限定类型,则基础类类型应具有用户声明的默认构造函数

综上所述,gcc中的错误似乎是完全正确的

[2003:8.5/9]:
如果没有为对象指定初始值设定项,则 对象是(可能是cv限定的)非POD类类型(或数组 其中,对象默认初始化;如果对象是 const限定类型,基础类类型应具有 用户声明的默认构造函数。否则,如果未使用初始值设定项 为非静态对象、对象及其子对象指定,如果 任何,具有不确定的初始值如果对象或其中任何一个 其子对象为常量限定类型,程序格式不正确。

以及:

[n3290:8.5/11]:
如果没有为对象指定初始值设定项,则默认初始化该对象如果不需要初始化 执行时,具有自动或动态存储持续时间的对象 不确定值。[注意:具有静态或线程存储的对象 持续时间为零初始化,见3.6.2.\结束注释

[n3290:8.5/6]:
默认初始化类型为
T
的对象意味着:

  • 如果
    T
    是(可能是cv限定的)类类型(第9条),则调用T的默认构造函数(如果
    T
    没有可访问的默认构造函数,则初始化是错误的)
  • 如果
    T
    是数组类型,则默认初始化每个元素
  • 否则,不执行初始化
如果程序调用常量限定类型的对象的默认初始化
T
T
应为具有用户提供的默认构造函数的类类型。


因此,MSVC在这方面比这两个标准都更为宽松。

C++17更新

C++17为const限定类类型具有默认构造函数的要求增加了一些细微差别。该标准现在定义了“const default constructable”概念:

7默认初始化T类型的对象意味着:

(7.1)-如果T是一种(可能是cv合格的)等级类型,则考虑施工人员。将枚举适用的构造函数,并通过重载解析选择初始值设定项()的最佳构造函数。调用这样选择的构造函数(参数列表为空),以初始化 对象。
(7.2)-如果T是数组类型,则每个元素默认初始化。
(7.3)-否则,不执行初始化。

如果T的默认初始化将调用用户提供的T构造函数(不是从基类继承的),或者如果

(7.4)T的每个直接非变量非静态数据成员M都有一个默认成员初始值设定项,或者,如果M是类类型X(或其数组),X是常量默认可构造的,
(7.5)-如果T是至少有一个非静态数据成员的联合,则正好有一个变体成员具有默认成员初始值设定项
(7.6)-如果T不是联合,则对于至少有一个非静态数据成员(如果有)的每个匿名联合成员,只有一个非静态数据成员具有默认成员初始值设定项,并且
(7.7)T的每个潜在构造基类都是常量默认可构造的。

如果程序调用常量限定类型的对象的默认初始化,TT应为常量默认可构造类类型或其数组


重复:除其他外。我无法在GCC 4.6.1中使用任何方言选项复制此内容。它只在我安装一个成员变量(如
int a;
)时才起作用,错误更准确:
'const struct Foo'没有用户提供的默认构造函数,隐式定义的构造函数没有初始化'int Foo::a'
@KerrekSB:我所做的就是
g++Foo.cpp
,和
g++--version
prints
g++(GCC)4.6.1
@frederoverflow:对不起,我指的是gcc4.6.2。最近更新了。应该是“允许”而不是“任务”,在右边,“去重复器”在我使用IMO的方式中是一样的,但是我们可以让它“允许”注释:如果你想解释为什么C风格的隐式零初始化结构在C++中不起作用,那是因为C和C++不同地实现了const。C++之前有代码> const 。有关更多信息,请参阅。