14

注意:我们在这里谈论(据说)符合 C++98 的编译器。这不是 C++11 问题。

我们的一个编译器有一个奇怪的行为,我们不确定这是否正常或者这是一个编译器错误:

// This struct has a default constructor
struct AAA
{
   AAA() : value(0) {}
   int value ;
} ;

// This struct has a member of type AAA and an array of int, both surrounded
// by ints
struct BBB
{
   int m_a ;
   AAA m_b ;
   int m_c ;
   int m_d[42] ;
} ;

当 BBB 这样初始化时:

BBB bbb = {0} ;

我们期望 BBB 的所有 POD 成员(包括 m_d,int 数组)都被初始化为零,并且 BBB 的所有非 POD 成员都被构造。

这适用于 AIX 的本机编译器、Linux/GCC-3.4、Windows/VisualC++ ......但不适用于 Solaris/SunStudio,其中只有非数组成员被零初始化。

我们在 C++98 标准(草案文档)中做了一些研究,发现以下内容:

[12.6.1 - 2]

当聚合(无论是类还是数组)包含类类型的成员并由大括号括起来的初始化器列表(8.5.1)初始化时,每个这样的成员都由相应的赋值表达式复制初始化(参见 8.5)。如果初始化器列表中的初始化器少于聚合的成员,则每个未显式初始化的成员都应默认初始化 (8.5)

然后:

[8.5 - 5]

对类型 T 的对象进行零初始化存储意味着:
如果 T 是标量类型 (3.9),则存储设置为转换为 T 的值 0(零);
— 如果 T 是非联合类类型,则每个非静态数据成员和每个基类子对象的存储都是零初始化的;
— 如果 T 是联合类型,则其第一个数据成员 89) 的存储是零初始化的;
— 如果 T 是数组类型,则每个元素的存储都是零初始化的;
— 如果 T 是引用类型,则不执行初始化。

接着:

默认初始化T 类型的对象意味着:
— 如果 T 是非 POD 类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是非良构的);
如果 T 是数组类型,则每个元素都是默认初始化的;
否则,对象的存储是零初始化的。

我读它的方式:SunStudio 应该零初始化整数数组 (BBB::m_d)

奇怪的是:如果我们从 AAA 中删除默认构造函数,那么 BBB 中的所有内容都是零初始化的。

问题:当 SunStudio 未能对包含非 POD 的结构的整数数组进行零初始化时,它的行为标准吗?或者这是一个编译器错误?

4

3 回答 3

2

这确实是 Sun/Solaris 的一个错误。你写的确实是应该发生的,你写的一切都是正确的。

于 2013-08-19T23:08:38.273 回答
1

这似乎是一个错误 - 我没有使用 Solaris 编译器的经验,但我使用过的所有其他编译器都允许这种初始化。

我建议通过更明确地解决这个问题:

 BBB bbb = {0, 0, 0, {0} };
于 2013-08-20T08:27:16.587 回答
1

这显然是 Sun CC 中的一个错误。标准是明确的,你对它的理解是正确的。

于 2013-08-20T08:24:12.873 回答