这个复制构造函数是个坏主意吗?

Is this copy constructor a bad idea?

所以,我觉得这是个坏主意:

class Foo
{
public:
  Foo(const Foo& from)
  {
     memcpy(this, &from, sizeof(Foo));

     m_someData = new int[m_dataLength];
     memcpy(m_someData, from.m_someData, m_dataLength * sizeof(int));
  }

  private:
    int* m_someData;
    int m_dataLength;

};

问题是:为什么?如果 memcpy 参数的类型(和大小)相同,布局相同,那么问题在哪里?

我看到的一个潜在问题是是否存在 stringvector<> 字段,但我不确定这是否是一个有效的问题。

如果 Foo 可以派生自,请考虑当您有一个从 Foo 派生的 Bar class 并复制构造一个 Foo 时会发生什么] 来自那个 Bar 实例。

如果您有任何虚拟方法,您的 sizeof(Foo) 包括编译器添加的用于实现虚拟方法(即 vtable)的任何信息,您绝对不想复制这些信息。

如果你没有任何虚方法,但是BarFoo添加了一个字段,那么你还有一个潜在的问题:那个字段可以存储在[的填充字节中=11=]。他们会被 memcpy.

破坏

最后:

One potential issue I see is if there is a string or vector<> field, but I'm not sure if that's a valid concern.

为什么不呢?明明会断,而且断得很厉害


您可以通过使用默认自动生成的拷贝构造函数来避免这个问题。如果您想为其添加逻辑,而不是被迫提及要复制的所有字段,请使用隐藏数据容器:

class Foo
{
public:
  Foo(const Foo& from)
  {
     m_Data = from.m_Data;

     m_Data.m_someData = new int[m_Data.m_dataLength];
     memcpy(m_Data.m_someData, from.m_Data.m_someData, m_Data.m_dataLength * sizeof(int));
  }

  private:
    struct Data {
      int* m_someData;
      int m_dataLength;
      // more fields
    };
    Data m_Data;

};

请注意这里的 m_Data = from.m_Data; 如何与您尝试使用 memcpy 达到的效果完全相同,只是它安全地做到了。

错误原因:

struct boom1 {
  boom1(const boom1& from) 
  // reason 1: not using an initialisation list means double-initialisation of members. inefficient.
  {
    // reason 2: undefined behaviour on all subsequent access to
    // this->_s or from._s after this line
    memcpy(this, &from, sizeof(from));

    // reason 3: what if someone derived from this class? didn't you just overwrite the RTTI info pointer??
  }

  // reason 4: c++ already generates a copy constructor that does the right thing automatically. why are you laying mines for other developers?

  std::string _s;
}

"yes but my particular class is a POD and I'm in control of it"...

...直到有人从中派生、修改或维护它。

不,不,不。这是永远不对的。总是错的。确保你的学生明白这一点。有一天,他可能正在为一辆 google 汽车编程。您现在不希望它 运行 影响您的孩子,对吗?