1

我想将派生结构的所有成员归零。

有数百个成员,并且每隔一段时间就会添加更多成员,所以我觉得显式初始化它们很容易出错。

结构没有虚函数,所有成员字段都是内置的。但是,由于具有非平凡的构造函数,它们不是 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));
    }
};

谢谢。

4

4 回答 4

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() { }
};
于 2011-08-16T17:58:11.857 回答
2

你不应该这样做。您应该在每个类中使用初始化列表,以避免必须这样做。在第一遍就完成它将是很多忙碌的工作,但如果之后遵循实践,那就是微不足道的了。

看到这个类似的问题

于 2011-08-16T18:00:43.270 回答
2

您应该将所有值显式设置为零并且不要使用 memset,因为它不可移植。编译器/内存分配可能存储了您可能正在覆盖的内务管理数据。

于 2011-08-16T18:00:51.370 回答
2

该标准并没有“不赞成这种做法”;它给出了未定义的行为

例如:

this + sizeof (Base)

C++ 标准中没有任何内容表明此表达式解析为指向 Derived 的指针。确实,既然是的类型thisDerived * const那么你所做的就是指针算术。C++ 将尝试添加到它,就好像this是一个指向数组的指针Derived,相当于this[sizeof(Base)]. 这可能不是你想要的。

如果您不确定如何正确行事,请不要走在未定义行为的黑暗走廊中。

最重要的是,即使您将体操指针指向实际工作,您的代码也会变得非常脆弱。它可能适用于您的编译器的这个版本,但它会在以后的版本中失败。做一些简单的事情,比如添加一个虚函数Base会导致代码混乱,因为你会破坏 vtable 指针。

在我看来,你有几个问题:

  1. 无需推导。如果Base其中没有任何虚拟内容,您为什么要公开从中派生?
  2. 胖接口。如果你看到一个班级开始有数百名成员,那么它可能做得太多了。
于 2011-08-16T18:08:28.087 回答