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

3Da*_*ave 4 c++ copy-constructor

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

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;

};
Run Code Online (Sandbox Code Playgroud)

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

我看到的一个潜在问题是,如果有一个string或一个vector<>字段,但我不确定这是否是一个有效的问题.

小智 7

如果Foo可以从中派生,请考虑当您从该实例Bar派生类时Foo复制构造a 时会发生什么.FooBar

如果您有任何虚拟方法,则sizeof(Foo)包括编译器添加的任何信息以实现虚拟方法(意味着vtable),您绝对不希望复制这些方法.

如果你没有任何虚拟方法,但是Bar添加了一个字段Foo,那么你仍然有一个潜在的问题:该字段可以存储在填充字节中Foo.他们会被一个人摧毁memcpy.

最后:

我看到的一个潜在问题是,如果有一个string或一个vector<>字段,但我不确定这是否是一个有效的问题.

为什么不呢?它显然会破裂,而且会破坏.


您可以使用默认自动生成的复制构造函数来避免此问题.如果要为其添加逻辑,而不是强制提及要复制的所有字段,请使用隐藏数据容器:

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;

};
Run Code Online (Sandbox Code Playgroud)

请注意m_Data = from.m_Data;这里有什么确实的效果memcpy,除了它安全地做到了.