1
19
序言:当我的回答还可以的时候,我发现 litb's answer 比我的好,因为:
所以,请在我之前考虑一下李特的回答。事实上,我建议这个问题的作者把李特的回答看作是正确的答案。 原始答案将一个真正的对象(即std::string)放入其中会中断,因为真正的对象将在memset之前初始化,然后被零覆盖。 使用初始化列表对G++不起作用(我很惊讶…)。在cmystruct构造函数体中初始化它。它将是C++友好的:
P.S.:我想你有 不 当然,控制我的结构。有了控件,您就可以直接在我的结构中添加构造函数,而忘记了继承。请注意,您可以将非虚拟方法添加到类C结构中,但它的行为仍像结构一样。 编辑:在LouFranco的评论后添加了缺失的括号。谢谢! 编辑2:我在G++上尝试了代码,由于某种原因,使用初始化列表不起作用。我使用body构造函数更正了代码。不过,该解决方案仍然有效。 请重新评估我的帖子,因为原始代码已更改(有关详细信息,请参阅更改日志)。 编辑3:在阅读了Rob的评论之后,我想他有一个值得讨论的观点:“同意,但是这可能是一个巨大的win32结构,随着一个新的sdk可能会改变,所以memset是未来的证明。” 我不同意:了解微软,它不会因为他们需要完美的向后兼容性而改变。他们将创建一个扩展的我的结构 前任 结构的初始布局与我的结构相同,结尾有附加的成员,可以通过类似于用于RegisterWindow、IIRC的结构的“大小”成员变量来识别。 因此,Rob的评论中唯一有效的一点就是“巨大的”结构。在这种情况下,也许memset更方便,但是您必须使我的结构成为cmystruct的变量成员,而不是从中继承。 我看到了另一个黑客,但我想这会因为可能的结构对齐问题而中断。 编辑4:请看一下弗兰克·克鲁格的解决方案。我不能保证它是可移植的(我想是),但从技术的角度来看,它仍然是有趣的,因为它显示了一个情况,在C++中,“这个”指针“地址”从它的基类移动到它的继承类。 |
2
84
您可以简单地对基值进行初始化,它的所有成员都将为零。这是有保证的
为了使这项工作正常,在基类中不应该有用户声明的构造函数,就像在您的示例中一样。
不讨厌
|
3
12
比记忆集好得多,你可以用这个小技巧来代替:
这将把所有成员初始化为0(或其默认值IIRC),无需为每个成员指定一个值。 |
4
9
这会让我觉得更安全,因为即使有一个
我相信你的解决方案会奏效,但我怀疑在混合时有什么保证
|
5
4
这是一个将C习语移植到C++的完美例子(以及为什么它不一定能正常工作……) 使用MeSET会遇到的问题是,在C++中,结构和类是完全相同的,除了默认情况下,结构具有公共可见性,并且类具有私有可见性。 因此,如果以后某个善意的程序员像这样改变了我的结构:
通过添加单个函数,您的memset现在可能会造成破坏。 在中有一个详细的讨论 comp.lang.c+ |
6
3
这些例子有“未指明的行为”。 对于非POD,编译器指定对象(所有基类和成员)的顺序是未指定的(ISO C++ 10/3)。考虑以下事项:
其布局如下:
或作为:
因此,直接在“this”地址上使用memset是非常不明确的行为。以上答案之一,乍一看似乎更安全:
然而,我相信,严格地说,这也会导致未指明的行为。我找不到规范性的文本,但是10/5中的注释说:“基类子对象的布局(3.7)可能与同一类型的最派生对象的布局不同。” 因此,i编译器可以使用不同的成员执行空间优化:
布局如下:
在32位系统上,由于“b”的对齐等原因,sizeof(b)最有可能是8个字节。但是,如果编译器打包数据成员,sizeof(c)也可以是“8”字节。因此,对memset的调用可能会覆盖给定给“c1”的值。 |
7
2
类或结构的精确布局在C++中是不保证的,这就是为什么你不应该从外部对它的大小做出假设(也就是说,如果你不是编译器)。 也许它可以工作,直到你找到一个编译器,它不在上面,或者你把一些vtable放到混合中。 |
8
1
如果您已经有了一个构造函数,那么为什么不在这里用n1=0;n2=0;初始化它呢--这当然是更多的 正常的 方式。 编辑:实际上,正如paercebal所示,ctor初始化更好。 |
9
1
我的意见是否定的。我也不确定它会得到什么。 随着CMystruct定义的更改和成员的添加/删除,这可能会导致错误。很容易。 为采用mystruct的cmystruct创建一个具有参数的构造函数。
或是其他的东西。然后可以初始化公共或私有的“mystrut”成员。 |
10
1
从ISO C++的观点来看,有两个问题: (1)物体是否为吊舱?首字母缩略词代表简单的旧数据,标准列举了POD中不能包含的内容(维基百科有一个很好的摘要)。如果它不是一个吊舱,你就不能记忆它。 (2)是否有所有零位无效的成员?在Windows和Unix上,空指针都是零位;不必是。浮点0在IEEE754和x86中都有所有的零位,这很常见。 FrankKruegers提示通过将memset限制在非pod类的pod库中来解决您的问题。 |
11
1
试试这个-超载新的。 编辑:我应该补充-这是安全的,因为之前的内存是零的 任何 调用构造函数。大缺陷-只有在动态分配对象时才有效。
|
12
1
如果MyOxStutt是您的代码,并且使用C++编译器很高兴,您可以将构造函数放置在一个类中,而不需要包装。
我不确定效率,但我讨厌在你还没有证明效率是必要的时候耍花招。 |
13
1
评论 litb's answer (似乎还不允许我直接评论): 即使有了这个漂亮的C++风格的解决方案,你也必须非常小心,不要把这个天真地应用到包含非POD成员的结构中。 有些编译器不再正确初始化。 见 this answer to a similar question . 我个人在VC2008上有过不好的体验,另外还有一个std::string。 |
14
0
我要做的是使用聚合初始化,但只为我关心的成员指定初始值设定项,例如:
其余的成员将初始化为适当类型的零(如Drealmer的post)。在这里,您相信微软不会通过在中间添加新的结构成员(一个合理的假设)而毫无理由地破坏兼容性。这个解决方案让我觉得是最优的——一条语句,没有类,没有内存集,没有关于浮点零或空指针的内部表示的假设。 我认为涉及继承的黑客是可怕的风格。公共继承对大多数读者来说意味着是一种。还要注意,您继承的类不是设计为基的。由于没有虚拟析构函数,通过指向基的指针删除派生类实例的客户端将调用未定义的行为。 |
15
0
我假设结构是提供给您的,不能修改。如果您可以更改结构,那么显而易见的解决方案是添加一个构造函数。 当你所需要的只是一个简单的宏来初始化你的结构时,不要用C++包装器过度设计你的代码。
|
16
0
这是一点代码,但它是可重用的;包括它一次,它应该适用于任何POD。您可以将此类的实例传递给任何需要my结构的函数,或者使用getpointer函数将其传递给将修改结构的函数。
这样,您就不必担心nulls都是0还是浮点表示。只要str是一个简单的聚合类型,就可以工作。当str不是一个简单的聚合类型时,您将得到一个编译时错误,因此您不必担心意外地误用了这个类型。另外,如果类型包含更复杂的内容,只要它有一个默认的构造函数,就可以:
不利的是,它会变慢,因为您要制作一个额外的临时副本,编译器会将每个成员单独分配给0,而不是一个memset。 |
Eddiex045 · 比较两个文本文件,匹配项转到一个新文件 2 年前 |
NOBUD · 最大堆插入函数实现C++ 2 年前 |
riasc · 嵌套贴图结构创建空贴图 6 年前 |
Akshay Barpute · cpp中的以下链表程序有什么问题? 6 年前 |
Batwoman05 · C++中是否有具有类似函数的树集数据结构 6 年前 |