可能的重复:
什么是三法则?
Array(const Array &arraytoCopy)
:size(arraytoCopy.size)
{
ptr=new int[size];
for(i=0;i<size;i++)
ptr[i]=arraytoCopy.ptr[i];
}
如果我不提供复制构造函数会发生什么。
可能的重复:
什么是三法则?
Array(const Array &arraytoCopy)
:size(arraytoCopy.size)
{
ptr=new int[size];
for(i=0;i<size;i++)
ptr[i]=arraytoCopy.ptr[i];
}
如果我不提供复制构造函数会发生什么。
将会发生的是,当您复制对象时,您将有多个实例指向同一个动态分配的数组。目前尚不清楚哪个实例应该负责在销毁时取消分配它。
如果该类应该拥有该数组,那么它将负责取消分配其资源。在这种情况下,它应该有一个复制构造函数和赋值运算符来复制数组的内容,以及一个调用delete[]
它的析构函数。这被称为三法则。在 C++11 中,它也应该有移动复制和移动赋值运算符。
如果该类不拥有该数组,则它可能一开始就不应该构造它。例如,它可以通过其构造函数接收指向外部分配数组的指针。
由于您有指向类中拥有的动态分配对象的原始指针,因此您必须正确提供复制构造函数和复制分配运算符函数。
考虑下面的类定义
class Array
{
public:
Array()
{
ptr = new int[10];
}
~Array(){
delete [] ptr;
}
private:
int *ptr;
};
当您实例化 Array 的两个对象时:
Array a1, a2;
a1 = a2;
现在a1.ptr
指向与销毁 a1、a2 期间相同的内存地址p2.ptr
,ptr 内存将被删除两次,这是未定义的行为。
使用std::vector<int> int_collection_;
是很好的解决方案,而不是使用原始指针。
class Array
{
public:
Array()
{
}
~Array(){
}
private:
std::vector<int> int_collection_;
};
如果您的意图是不允许复制您的类实例,您可以将您的复制构造函数定义为私有并且不提供实现,以便编译器可以捕获这些情况,例如
class Array
{
...
private:
Array(const Array &arraytoCopy); // not implemented
};
在这种情况下,您不必担心上述指针所有权问题。