从C ++ 11标准§8.5p6我们有:
如果程序要求默认初始化a的对象 const限定类型T,T应为具有用户提供的类类型 默认构造函数。
以下代码应不编译。但在Coliru和Ideone都有。
class A{};
int main() {
const A a;
}
修改
在尝试理解这里发生的事情时,我最终得到了以下代码,这些代码编译(至少它符合标准,因为 A
有一个用户提供的构造函数)。但后来我想到了以下问题:哪个标准子句确保a.b.j
初始化为0(参见Ideone中的代码),如下所示?
#include <iostream>
struct B { int j; B(){ std::cout << "B()" << '\n'; } };
struct A
{
struct B b;
int i;
public:
A(): i(1) { std::cout << "A()" << '\n'; }
};
int main() {
const A a;
std::cout << a.b.j << '\n';
std::cout << a.i << '\n';
}
EDIT1:
很抱歉上面的编辑,但我还没有使用过Unix。上周Dietmar Kühl提请我注意"Most UNIXes start off with zero initialized pages"这一事实。因此,正如我所想的那样,a.b.j因为初始化而不是0。事实上,我刚用VS2010编译代码,a.b.j的结果是一个酉值,正如预期的那样。因此,应忽略编辑中的问题。
但我很想知道clang ++或g ++是否也会为第二个片段显示错误。谢谢。
答案 0 :(得分:4)
在研究了初始化和汇总的规则后,我得出结论,你是对的 -
您的编译器正在使用快捷方式,因为没有成员,因此不需要初始化几乎。 (有趣的是,the ancient GCC 4.1.2 rejects the program。)
不幸的是我没有什么可引用的,因为在这种情况下根本没有规则覆盖[C++11: 8.5/6]
。
至于为什么标准不允许这样做,为什么要这样呢?空类几乎没有用,我看不出有理由为这个边缘情况积极地为更广泛,更有用的rule写一个豁免。
答案 1 :(得分:1)
考虑到第7.1.6.1节第2段第2段中的注释:cv-qualifiers,其中有以下内容:
似乎确实编译器确实很奇怪。2 [注意:声明变量const会影响其链接(7.1.1) 及其在常量表达式中的可用性(5.19)。如8.5中所述, const限定类型的对象或子对象的定义必须 指定初始值设定项或进行默认初始化。 -结束 注意]
虽然如果要添加数据成员,代码将不会在ideone中编译,但至少会在MS VC ++ 2010中编译。 在您提供的报价中,没有任何关于数据成员的说法。