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

时间:2015-10-21 13:25:10

标签: 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;

};

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

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

2 个答案:

答案 0 :(得分:7)

如果可以推导出Foo,请考虑当您从Bar派生Foo类时会发生什么,并从{{1}复制构造Foo实例。

如果你有任何虚拟方法,你的Bar包括编译器为实现虚拟方法(意味着vtable)而添加的任何信息,你肯定不想复制它们。

如果您没有任何虚拟方法,但sizeof(Foo)Bar添加了一个字段,那么您仍有潜在的问题:该字段可以存储在{{1的填充字节中}}。他们会受到Foo的打击。

最后:

  

我看到的一个潜在问题是,如果有Foomemcpy字段,但我不确定这是否是一个有效的问题。

为什么不呢?它会明显破裂,而且会破坏。

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

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; }; 如何与m_Data = from.m_Data;达到的确切效果相同,但安全性除外。

答案 1 :(得分:2)

为什么这是错的:

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;
}

“是的,但我的特殊课程是POD而且我能控制它”......

...直到其他人从中获取,修改它或尝试维护它。

不,不,不。这是永远不对的。总是错的。确保你的学生理解这一点。有一天,他可能正在编写谷歌汽车。你现在不想让它过你的孩子吗?