为数组动态分配内存时,为什么需要复制构造函数?

时间:2012-11-09 06:41:27

标签: c++ dynamic copy-constructor

  

可能重复:
  What is The Rule of Three?

Array(const Array &arraytoCopy)
:size(arraytoCopy.size)
{
    ptr=new int[size];
    for(i=0;i<size;i++)
        ptr[i]=arraytoCopy.ptr[i];
}

如果我不提供复制构造函数,会发生什么。

3 个答案:

答案 0 :(得分:3)

当您复制对象时,您将有多个实例指向同一个动态分配的数组。目前尚不清楚哪个实例应该在销毁时解除分配。

如果该类应该拥有该数组,那么它将负责取消分配其资源。在这种情况下,它应该有一个复制构造函数和赋值运算符,它们复制数组的内容,并在其上调用delete[]的析构函数。这被称为rule of three。在C ++ 11中,它也应该有移动复制和移动赋值运算符。

如果该类不拥有该数组,则可能不应该首先构造它。例如,它可以通过其构造函数接收指向外部分配的数组的指针。

答案 1 :(得分:2)

由于您拥有在类中拥有动态分配对象的原始指针,因此必须正确提供复制构造函数和复制赋值运算符函数。

考虑以下课程定义

class Array
{
public:
  Array()
  { 
     ptr = new int[10];
  }
  ~Array(){
     delete [] ptr;
  }
private:
  int *ptr;  
};

当您实例化Array的两个对象时:

Array a1, a2;
a1 = a2;

现在a1.ptr指向与p2.ptr相同的内存地址 在a1,a2的销毁过程中,ptr内存将被删除两次,这是未定义的行为。

使用std::vector<int> int_collection_;是一个很好的解决方案,而不是使用原始指针。

class Array
    {
    public:
      Array()
      {           
      }
      ~Array(){             
      }
    private:
      std::vector<int> int_collection_;
    };

答案 2 :(得分:0)

如果您的目的是不允许复制类实例,则可以将复制构造函数定义为私有,并且不提供实现,以便编译器可以捕获这些情况,例如。

class Array
{
    ...
private:
    Array(const Array &arraytoCopy); // not implemented
};

在这种情况下,您不必担心上述指针所有权问题。