使用memcpy复制对象数组

时间:2015-05-22 00:36:12

标签: c++ arrays object memcpy

最近我在项目中遇到了错误双重免费或损坏错误。在一些测试运行之后,问题被固定到使用memcpy的复制功能。

  class Pen
  {    string make;
       string model;
       string color;
       public:
       Pen();
  }

  class A
  { private:

    Pen* array; //an array that stores pen objects 
    int NumOfItem;   
    int Maxsize;        
    void CopyArray(const A& source);

    public:
    A();
    A(const A& source);//copy constructor where uses the CopyArray private mentioned below
    ~A();
  }






  void A::CopyArray(const A& source)
  {       
    memcpy(array, source.array, len * sizeof(Pen));//
    return;
  }

  void A::A(const A& source)//copy constructor that performs a deep copy from B
  {    array = new Pen[source.NumOfItem];
       NumOfItem = source.NumOfItem;
       MaxisIze=source.Maxize;
       CopyArray(source);
  }

当我更改我的代码并使用for循环复制每个参数时,它可以工作。 我仍然试图理解为什么memcpy会导致问题,如果只是将所有数据按位复制到新对象......(对于凌乱的格式抱歉..)

2 个答案:

答案 0 :(得分:10)

使用memcpy的问题在于它绕过了复制构造函数。只有当您的类由基元组成时才可以。

但是,Pen类具有std::string类型的非原始数据成员。这些对象需要复制复制构造函数的调用。 memcpy不会对复制构造函数执行任何调用,这会导致std::string的内部表示变为共享,从而导致销毁时出现未定义的行为。

另一方面,使用循环复制会调用复制构造函数,因此代码运行时没有问题。

C ++标准库提供了一个实用程序函数,用于复制名为std::copy的范围。使用此函数可以避免您看到的问题,因为它会根据需要调用复制构造函数。

答案 1 :(得分:7)

您只能使用memcpy()复制trivially copyable的对象。让我们看看Pen是否符合此要求。

#include <string>
using namespace std;

class Pen {
    string make;
    string model;
    string color;
    public:
    Pen();
};

static_assert(std::is_trivially_copyable<Pen>::value, "Pen is not trivially copyable");

编译时,将返回错误:

blah.cc:12:1: error: static_assert failed "Pen is not trivially copyable"
static_assert(std::is_trivially_copyable<Pen>::value, "Pen is not trivially copyable");
^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

因此,我们可以清楚地看到Pen并非易于复制,因此我们无法使用memcpy()。您应该使用std::copy代替。