使用 memcpy 复制对象数组
Using memcpy to copy an array of objects
最近在我的项目中遇到了错误double free or corruption error。经过一些测试运行后,问题被确定为使用 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 会导致问题,如果它所做的只是将所有数据按位复制到新对象......(抱歉格式混乱..)
使用 memcpy
的问题在于它绕过了复制构造函数。仅当您的 class 由基元组成时才可以。
但是,Pen
class 具有 std::string
类型的非原始数据成员。这些对象需要调用复制构造函数才能复制。 memcpy
不执行任何对复制构造函数的调用,这导致 std::string
的内部表示被共享,这反过来会导致未定义的销毁行为。
另一方面,使用循环进行复制会调用复制构造函数,因此您的代码可以毫无问题地运行。
C++ 标准库提供了一个名为 std::copy
的用于复制范围的实用函数。使用此函数可以避免您看到的问题,因为它会根据需要调用复制构造函数。
您只能使用 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");
编译时,这将 return 错误:
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
。
最近在我的项目中遇到了错误double free or corruption error。经过一些测试运行后,问题被确定为使用 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 会导致问题,如果它所做的只是将所有数据按位复制到新对象......(抱歉格式混乱..)
使用 memcpy
的问题在于它绕过了复制构造函数。仅当您的 class 由基元组成时才可以。
但是,Pen
class 具有 std::string
类型的非原始数据成员。这些对象需要调用复制构造函数才能复制。 memcpy
不执行任何对复制构造函数的调用,这导致 std::string
的内部表示被共享,这反过来会导致未定义的销毁行为。
另一方面,使用循环进行复制会调用复制构造函数,因此您的代码可以毫无问题地运行。
C++ 标准库提供了一个名为 std::copy
的用于复制范围的实用函数。使用此函数可以避免您看到的问题,因为它会根据需要调用复制构造函数。
您只能使用 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");
编译时,这将 return 错误:
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
。