我想将派生结构的所有成员归零。
每隔一段时间就会有数百个成员和更多成员被添加,所以我觉得明确地初始化它们容易出错。
结构没有虚函数,所有成员字段都是内置的。然而,由于拥有非平凡的构造函数,它们不是POD。
除了对练习的标准皱眉外,您是否看到以下任何问题?
struct Base
{
// Stuff
};
struct Derived : public Base
{
// Hundreds of fields of different built-in types
// including arrays
Derived()
{
::memset(reinterpret_cast<char*>this + sizeof (Base), 0, sizeof *this - sizeof (Base));
}
};
感谢。
答案 0 :(得分:9)
这假定Base
基类子对象位于Derived
的开头。如果添加另一个基类,这将不起作用。
此外,您的代码是错误的:指针算术是根据对象执行的,而不是以字节为单位。您需要使用reinterpret_cast<char*>(this)
以字节为单位执行算术运算。无论如何,你仍然不应该这样做。
考虑以下非丑陋的,符合标准的方法,利用值初始化:
struct Derived : public Base
{
struct DerivedMembers { /* ... */ }
DerivedMembers data;
Derived() : data() { }
};
只要DerivedMembers
没有构造函数,就会初始化data
的每个数据成员,这看起来就像你想要的行为。
或者,如果您希望在不使用“data
”成员变量的情况下访问成员,请考虑使用其他基类:
struct DerivedMembers { /* ... */ }
struct Derived : Base, DerivedMembers
{
Derived() : DerivedMembers() { }
};
答案 1 :(得分:2)
你不应该这样做。您应该在每个类中使用初始化列表,以避免必须执行此操作。在第一遍中完成它将是一项繁忙的工作,但如果在那之后实践被遵循它是微不足道的。
请参阅此similar question:
答案 2 :(得分:2)
您应该将所有值显式设置为零,而不使用memset,因为这不可移植。编译器/内存分配可能会存储您可能会覆盖的内务处理数据。
答案 3 :(得分:2)
标准并没有“对实践不屑一顾”;它给出了未定义的行为。
例如:
this + sizeof (Base)
C ++标准中没有任何内容表明此表达式解析为指向Derived的指针。实际上,由于this
的类型是Derived * const
,那么你所做的就是指针算术。 C ++会尝试添加它,好像this
是指向Derived
数组的指针,相当于this[sizeof(Base)]
。这可能不是你想要的。
如果您不确定如何正确行事,请不要走未定义行为的黑暗走廊。
最重要的是,即使你把体操指向实际工作,你的代码也会变得非常脆弱。它可能适用于此版本的编译器,但稍后会失败。做一些简单的事情,例如向Base
添加虚拟函数会导致代码中出现 chaos ,因为你会破坏vtable指针。
在我看来,你有几个问题:
Base
中没有虚拟内容,为什么要公开衍生出来呢?