这个C ++结构初始化技巧是否安全? [英] Is this C++ structure initialization trick safe?
问题描述
不必记住初始化一个简单的C结构,我可以从它派生并在构造函数中将其归零,如下所示:
Instead of having to remember to initialize a simple 'C' structure, I might derive from it and zero it in the constructor like this:
struct MY_STRUCT
{
int n1;
int n2;
};
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct()
{
memset(this, 0, sizeof(MY_STRUCT));
}
};
这个技巧通常用于初始化Win32结构,有时可以设置无处不在的 cbSize member。
This trick is often used to initialize Win32 structures and can sometimes set the ubiquitous cbSize member.
现在,只要没有一个虚函数表用于memset调用destroy,这是一个安全的做法吗?
Now, as long as there isn't a virtual function table for the memset call to destroy, is this a safe practice?
推荐答案
PREAMBLE:
虽然我的答案还是,我发现litb's answer 相当优于我,因为:
PREAMBLE:
While my answer is still Ok, I find litb's answer quite superior to mine because:
- 它教我一个我不知道的骗子(litb的答案通常有这个效果,但这是我第一次写下来)
- 它回答的是正确的问题(也就是将初始结构的部分初始化为零)
litb的答案在我之前。
So please, consider litb's answer before mine. In fact, I suggest the question's author to consider litb's answer as the right one.
投放一个真正的对象(即std :: string)等会破坏,因为真正的对象将在memset之前被初始化,然后被零覆盖。
Putting a true object (i.e. std::string) etc. inside will break, because the true object will be initialized before the memset, and then, overwritten by zeroes.
初始化列表不工作的g ++(我很惊讶...)。在CMyStruct构造函数体中初始化它。它将是C ++友好的:
Using the initialization list doesn't work for g++ (I'm surprised...). Initialize it instead in the CMyStruct constructor body. It will be C++ friendly:
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct() { n1 = 0 ; n2 = 0 ; }
};
PS:我假设你对MY_STRUCT有没有 。使用控件,您将直接在MY_STRUCT中添加构造函数,并忘记关于继承。注意,你可以将非虚拟方法添加到类似C的结构,并且仍然具有结构的作用。
P.S.: I assumed you did have no control over MY_STRUCT, of course. With control, you would have added the constructor directly inside MY_STRUCT and forgotten about inheritance. Note that you can add non-virtual methods to a C-like struct, and still have it behave as a struct.
编辑:添加缺少括号,在Lou Franco的评论。谢谢!
Added missing parenthesis, after Lou Franco's comment. Thanks!
编辑2:我试过g ++上的代码,并且由于某种原因,使用初始化列表不工作。我使用正文构造函数更正了代码。
EDIT 2 : I tried the code on g++, and for some reason, using the initialization list does not work. I corrected the code using the body constructor. The solution is still valid, though.
请重新评估我的帖子,因为原始代码已更改(有关更多信息,请参阅changelog)。
Please reevaluate my post, as the original code was changed (see changelog for more info).
编辑3:阅读Rob的评论后,我想他有一个值得讨论的问题:同意,但这可能是一个巨大的Win32结构,可能会随着新的SDK改变,所以memset是未来的证明。
EDIT 3 : After reading Rob's comment, I guess he has a point worthy of discussion: "Agreed, but this could be an enormous Win32 structure which may change with a new SDK, so a memset is future proof."
我不同意:知道微软,它不会改变,因为他们需要完美的向后兼容性。他们将创建一个扩展的MY_STRUCT Ex 结构,它与MY_STRUCT具有相同的初始布局,在末尾使用了addnal成员,通过一个size成员变量,如用于RegisterWindow的结构体IIRC可以识别。
I disagree: Knowing Microsoft, it won't change because of their need for perfect backward compatibility. They will create instead an extended MY_STRUCTEx struct with the same initial layout as MY_STRUCT, with additionnal members at the end, and recognizable through a "size" member variable like the struct used for a RegisterWindow, IIRC.
因此,Rob的评论中剩下的唯一有效点是巨大的结构。在这种情况下,memset可能更方便,但是你必须让MY_STRUCT成为CMyStruct的可变成员,而不是继承它。
So the only valid point remaining from Rob's comment is the "enormous" struct. In this case, perhaps a memset is more convenient, but you will have to make MY_STRUCT a variable member of CMyStruct instead of inheriting from it.
我看到另一个黑客,我猜这会破坏,因为可能的结构对齐问题。
I see another hack, but I guess this would break because of possible struct alignment problem.
编辑4:请看看弗兰克·克鲁格的解决方案。我不能承诺它是可移植的(我猜是),但它仍然是有趣的从技术角度来看,因为它显示了一个案例,在C + +,这个指针地址从其基类移动到其继承类。
EDIT 4: Please take a look at Frank Krueger's solution. I can't promise it's portable (I guess it is), but it is still interesting from a technical viewpoint because it shows one case where, in C++, the "this" pointer "address" moves from its base class to its inherited class.
这篇关于这个C ++结构初始化技巧是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!