使用memset对派生结构体进行归零



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

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

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

谢谢。

假设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() { }
};

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

参见类似的问题:

您应该显式地将所有值设置为零,而不要使用memset,因为这是不可移植的。编译器/内存分配可能存储有您可能会覆盖的日常数据。

标准不"不赞成实践";它给出未定义的行为

例如:

this + sizeof (Base)

c++标准中没有规定这个表达式解析为指向Derived的指针。实际上,由于this的类型是Derived * const,那么您所做的就是指针算术。c++将尝试将this添加为指向Derived(相当于this[sizeof(Base)])数组的指针。这可能不是你想要的。

如果你不确定如何正确地做这件事,就不要走未定义行为的黑暗走廊。

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

我觉得你有几个问题:

  1. 不必要的推导。如果Base没有任何虚拟的东西,你为什么要公开派生它?
  2. 一个胖接口。如果你看到一个类开始有数百个
成员,那么它可能做得太多了。

最新更新