C++ 是否支持允许我们将对象及其所有填充字段初始化为零的语言结构。我在 cppreference.com 中找到了一些关于零初始化的令人鼓舞的措辞,这表明在某些情况下,填充字节也将被归零。
引用 cppreference.com: 零初始化
在以下情况下执行零初始化:
- 作为非类类型和没有构造函数的值初始化类类型成员的值初始化序列的一部分,包括未提供初始化器的聚合元素的值初始化。
零初始化的效果是:
- 如果 T 是标量类型,则对象的初始值是显式转换为 T 的整数常量零。
- 如果 T 是非联合类类型,则所有基类和非静态数据成员都初始化为零,并且所有填充都初始化为零位。构造函数(如果有)将被忽略。
- ...
人们会在value-initialization、aggregate-initialization和list-initialization中找到对零初始化的引用。
我使用相当最新的 GCC 和 clang C++ 编译器进行了测试,它们的行为似乎不同。
坦率地说,我努力解析这些规则,特别是考虑到不同的编译器行为,我无法弄清楚如何正确解释这些规则。
请参阅此处的代码(需要最低 C++11)。结果如下:
给定:Foo
struct Foo
{
char x;
int y;
char z;
};
构造 | 克++ | 铿锵++ |
---|---|---|
富() | x:[----][0x42][0x43][0x44],v: 0 |
x:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
|
z:[----][0x4A][0x4B][0x4C],v: 0 |
z:[----][----][----][----],v: 0 |
|
富{} | x:[----][----][----][----],v: 0 |
x:[----][0x42][0x43][0x44],v: 0 |
y:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
|
z:[----][----][----][----],v: 0 |
z:[----][0x4A][0x4B][0x4C],v: 0 |
这里[----]
表示一个包含所有位 0 的字节,并且[0x..]
是垃圾值。
如您所见,编译器输出表明填充未初始化。Foo()
和都是Foo{}
值初始化。此外还有Foo{}
一个聚合初始化,缺少初始化程序。为什么没有触发零初始化规则?为什么没有触发填充规则?
我已经明白依赖填充字节为零不是一个好主意,甚至可能是未定义的行为,但我认为这不是这个问题的重点。
- 问题 1:标准是否提供了一种可靠地初始化填充字节的方法?
- 问题 2:另请参阅:c 是否初始化结构填充。是否适用?
- 问题 3:这些编译器是否符合标准?
- 问题 4:编译器明显不同的行为的解释是什么?