可以在不调用 memset 的情况下从构造函数初始化器列表中将成员结构设为零吗?
Posted
技术标签:
【中文标题】可以在不调用 memset 的情况下从构造函数初始化器列表中将成员结构设为零吗?【英文标题】:Can a member struct be zero-init from the constructor initializer list without calling memset? 【发布时间】:2010-05-12 07:27:47 【问题描述】:假设我有以下结构声明(没有构造函数的简单结构)。
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 &_foo。这是我一直做的......
但是,我确实注意到如果将 _foo 添加到不带参数的构造函数的初始化列表中,如下所示:
CFoobar::CFoobar()
: _foo()
这似乎将 _foo 的成员变量清零。至少 linux 上的 g++ 是这样的。
现在我的问题是:这是标准 C++,还是编译器特有的行为?
如果这是标准行为,有人可以从官方来源引用我的参考吗?对于更复杂的结构和类的隐式零初始化行为有任何“陷阱”吗?
【问题讨论】:
【参考方案1】:是的,这是根据标准定义的行为。 12.6.2 [class.base.init] / 3 : "如果mem-initializer的expression-list被省略,则基类或成员子对象为值初始化。”
但请注意,如果 Foo
不是 POD 类型但仍然没有用户声明的构造函数(例如,它有 std::string
类型),那么一些非常流行的编译器将无法正确 value-初始化它。
当您使用 ()
作为构造函数初始化器列表中的初始化器时,我所知道的所有编译器都会正确执行 POD 成员的值初始化。
【讨论】:
"一些流行的编译器" = VC6 我假设?因为在过去的 10 年里,我没有在任何编译器中看到错误的行为。 @MSalters:不幸的是,还有 VS2005 和 VS2008 编译器。我没有在 VS2010 上尝试过。 @MSalters:它不仅适用于没有用户声明的构造函数的非 POD 结构成员;其他类型正常工作。 Connect上有几篇关于此的报道。这是我找到的:connect.microsoft.com/VisualStudio/feedback/details/484295/… 我的意思是“注意,它只适用于...”,而不是“不只是...”,但为时已晚,无法编辑。还有,即使VC6很流行我也会一针见血的拒绝承认这个事实。 :) 啊哈,至少还有一个附加标准(存在基类)。这或许可以解释为什么我没有注意到。【参考方案2】:我觉得阅读标准很难,但我认为:
对 T 类型的对象进行值初始化意味着: 如果 T 是没有用户声明的构造函数的非联合类类型,则每个非静态数据成员和基类 T 的类组件是值初始化的 这种类对象的值初始化可以通过对对象进行零初始化,然后调用默认构造函数来实现。
第 8.5 节
【讨论】:
8.5 需要与 12.6.2 一起阅读才能知道这个成员初始化器确实需要 value-initialization 。【参考方案3】:相当于float foo = float();
它会将对象归零,即使值表示不是全位为零。 IE。比memset()
还要好。
【讨论】:
以上是关于可以在不调用 memset 的情况下从构造函数初始化器列表中将成员结构设为零吗?的主要内容,如果未能解决你的问题,请参考以下文章