使用内存复制对象数组

Using memcpy to copy an array of objects

本文关键字:对象 数组 复制 内存      更新时间:2023-10-16

最近我在我的项目中遇到了错误的双重自由或腐败错误。经过一些测试运行后,问题被确定为使用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的问题是它绕过了复制构造函数。只有当你的类由原语组成时,这才可以。

然而,Pen类具有std::string类型的非原语数据成员。这些对象需要调用复制构造函数进行复制。memcpy不执行任何复制构造函数的调用,这导致std::string的内部表示被共享,这反过来导致销毁时的未定义行为。

另一方面,使用循环进行复制会调用复制构造函数,因此您的代码可以正常运行。

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

您只能使用memcpy()来复制一般可复制的对象。让我们看看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