我不是必须记住初始化一个简单的'C'结构,而是可以从它派生并在构造函数中将它归零,如下所示:
struct MY_STRUCT { int n1; int n2; }; class CMyStruct : public MY_STRUCT { public: CMyStruct() { memset(this, 0, sizeof(MY_STRUCT)); } };
这个技巧通常用于初始化Win32结构,有时可以设置无处不在的cbSize成员.
现在,只要memset调用没有虚函数表来销毁,这是一种安全的做法吗?
您可以简单地初始化基数,并将其所有成员清零.这是有保证的
struct MY_STRUCT { int n1; int n2; }; class CMyStruct : public MY_STRUCT { public: CMyStruct():MY_STRUCT() { } };
为了使其工作,基类中应该没有用户声明的构造函数,就像在您的示例中一样.
memset
对此并不讨厌.它不能保证memset
在您的代码中有效,即使它应该在实践中起作用.
虽然我的答案仍然没问题,但我发现litb的答案远非我的,因为:
它告诉我一个我不知道的技巧(litb的答案通常有这种效果,但这是我第一次写下来)
它完全回答了问题(即将原始struct的部分初始化为零)
所以,请在我之前考虑一下litb的答案.事实上,我建议问题的作者将litb的答案视为正确答案.
将一个真实对象(即std :: string)等放入其中将会破坏,因为真实对象将在memset之前初始化,然后由零覆盖.
使用初始化列表对g ++不起作用(我很惊讶......).而是在CMyStruct构造函数体中初始化它.它将是C++友好的:
class CMyStruct : public MY_STRUCT { public: CMyStruct() { n1 = 0 ; n2 = 0 ; } };
PS:我当然认为你确实无法控制MY_STRUCT.使用控件,您可以直接在MY_STRUCT中添加构造函数,并忘记继承.请注意,您可以将非虚方法添加到类似C的结构中,并且仍然将其表现为结构.
编辑:在Lou Franco的评论之后添加了缺失的括号.谢谢!
编辑2:我在g ++上尝试了代码,由于某种原因,使用初始化列表不起作用.我使用body构造函数更正了代码.不过,解决方案仍然有效.
请重新评估我的帖子,因为原始代码已更改(有关详细信息,请参阅changelog).
编辑3:在阅读Rob的评论之后,我猜他有一个值得讨论的观点:"同意,但这可能是一个巨大的Win32结构,可能会随着新的SDK而改变,因此memset是未来的证明."
我不同意:了解微软,它不会因为需要完美的向后兼容性而改变.他们将创建一个扩展的MY_STRUCT Ex结构,其初始布局与MY_STRUCT相同,末尾有附加成员,并且可通过"size"成员变量识别,如用于RegisterWindow,IIRC的结构.
所以Rob的评论中剩下的唯一有效点是"巨大的"结构.在这种情况下,也许memset更方便,但是你必须使MY_STRUCT成为CMyStruct的变量成员而不是继承它.
我看到另一个黑客,但我想这会因为可能的结构对齐问题而中断.
编辑4:请看看Frank Krueger的解决方案.我不能保证它是可移植的(我猜它是),但从技术角度来看它仍然很有趣,因为它显示了一种情况,在C++中,"this"指针"地址"从其基类移动到其继承类.
比memset好多了,你可以用这个小技巧代替:
MY_STRUCT foo = { 0 };
这会将所有成员初始化为0(或其默认值iirc),无需为每个成员指定值.
这会让我感觉更安全,因为它应该工作,即使有一个vtable
(或编译器会尖叫).
memset(static_cast(this), 0, sizeof(MY_STRUCT));
我相信你的解决方案会起作用,但我怀疑在混音memset
和课程时有任何保证.