假设我有以下结构声明(没有构造函数的简单结构)。
struct Foo
{
int x;
int y;
int z;
char szData[DATA_SIZE];
};
现在假设这个结构是C ++类的成员,如下所示:
class CFoobar
{
Foo _foo;
public:
CFoobar();
};
如果我按如下方式声明CFoobar的构造函数:
CFoobar::CFoobar()
{
printf("_foo = {%d, %d, %d}\n", _foo.x, _foo.y,_foo.z);
for (int x = 0; x < 100; x++)
printf("%d\n", _foo.szData[x]);
}
正如您所料,当CFoobar的构造函数运行时,垃圾数据被打印出来显然,简单的解决方法是memset或ZeroMemory&amp; _foo。这就是我一直以来所做的......
但是,我注意到如果将_foo添加到构造函数的初始化列表中而没有参数,如下所示:
CFoobar::CFoobar()
: _foo()
{
这似乎将_foo的成员变量清零。至少就是linux上的g ++就是这种情况。
现在我的问题是:这是标准的C ++,还是这种编译器的特定行为?
如果是标准行为,有人可以引用我的官方来源参考吗?关于更复杂的结构和类的隐式零初始化行为的任何“陷阱”?
答案 0 :(得分:11)
是的,这是根据标准定义的行为。 12.6.2 [class.base.init] / 3:“如果省略 mem-initializer 的表达式列表,则基类或成员子对象是值初始化“。
但请注意,如果Foo
不是POD类型但仍然没有用户声明的构造函数(例如它有std::string
类型),那么一些非常流行的编译器将无法正确< em> value-initialize it。
当您在构造函数初始化列表中使用()
作为初始化程序时,我所知道的所有编译器都会正确执行POD成员的值初始化。
答案 1 :(得分:2)
我觉得很难阅读标准,但我发现它我认为:
对T类型的对象进行值初始化意味着:
如果T是没有用户声明的构造函数的非联合类类型,那么每个非静态数据成员和基础 - T的类组件是值初始化的 这种类对象的值初始化可以通过零初始化对象然后调用默认构造函数来实现。
第8.5节
答案 2 :(得分:1)
相当于float foo = float();
即使值表示不是全位 - 零,它也会使对象归零。即它甚至比memset()
更好。