使用memcpy复制对象数组

Gal*_*age 3 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);
  }
Run Code Online (Sandbox Code Playgroud)

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

das*_*ght 10

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

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

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

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

  • @Lzy`std :: string`对象里面有指针来引用字符串中的实际数据.这些指针在销毁时被取消分配.当你销毁`Pen`时,它的所有字符串也会被破坏.在'memcpy`之后,`std :: string`的两个实例指向同一个内存.当复制的"Pen"被破坏时,原始中的指针变为无效,反之亦然,这取决于首先被破坏的内容.当另一个对象被销毁时,它会向运算符`delete []`提交无效指针,这是一种经常导致程序崩溃的未定义行为. (3认同)
  • @Lzy `int`、`long`、`float`、`double` 等是原始数据类型。类和由它们组成的“结构”(和/或由基元组成的其他“结构”)可以使用“memcpy”进行复制。这是由“琐碎复制”的概念概括的,在另一个答案的链接中进行了解释。 (2认同)

Bil*_*nch 7

您只能用于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");
Run Code Online (Sandbox Code Playgroud)

编译时,这将返回错误:

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");
^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

所以,我们可以清楚地看到,这Pen不是简单的可复制,所以我们不能使用memcpy()它.你可能应该使用std::copy.