为什么在此副本分配结束时未获得所获得的资源?

时间:2016-02-03 05:26:15

标签: c++

我正在阅读C ++编程语言第4版,我到达了有关复制分配构造函数的部分。作者有一个名为Vector的类,他定义了像这样的

复制赋值构造函数
Vector& Vector::operator=(const Vector& a)
{
   double* p = new double[a.sz];
   for (int i=0; i != a.sz; ++i)
      p[i] = a.elem[i];
   delete[] elem;
   elem = p;
   sz = a.sz;
   return *this
}

(对于拥有该书的人,可以在第74页找到) 现在,我的问题是:如果p有一个新资源,为什么它不会在返回之前发布删除?或以另一种方式说:为什么缺少delete [] p被认为是内存泄漏?

我问这个是因为,到目前为止,我已经注意到,对于每个,必须有删除以及我看过的问题“我应该使用删除这里“说明对于每个新的,应该删除。 我看到了这个问题Must new always be followed by delete?但是在这种情况下,程序结束并且资源被释放,而在上面的代码中程序继续。

(另外,在一个附带问题上,elem = p语句是否会调用复制赋值构造函数?这行混淆了我,因为它似乎会调用它并进行一种无限循环)

4 个答案:

答案 0 :(得分:2)

一般模式是,如果一个类拥有一个资源,那么它的析构函数将释放资源(参见RAII)。所以,毫无疑问,有类似

的东西
Vector::~Vector()
{
    delete[] elem;
}

其他地方。

在对象生命周期的各个点,其他操作可能会释放资源,例如,在这种情况下,复制赋值构造函数。如果这样做,那么资源将被小心地重新分配,或者它将被设置为指示没有任何东西要释放的状态(例如,通过将其设置为nullptr)。

关于你的第二个问题。 Vector的复制赋值运算符只是为指针分配一个新值 - 涉及 no 递归。

答案 1 :(得分:2)

对于每个被执行的new,应该有一个delete某个地方被执行。它不一定应该在同一个功能中。此外,程序文本中出现一次delete可能会匹配new的几种不同事件,反之亦然。执行计数必须匹配,而不是文本事件。

elem = p不会打电话给任何人。 elemp是指针。它是内置的类型分配。

答案 2 :(得分:1)

您担心的delete将在本案的destructor中完成。

代码正在做的是为数据创建空间,复制数据并释放旧内存。让新内存稍后处理,RAII

旁注:

 elem = p

它不会调用class的复制操作,因为它们是指向POD的指针,普通的旧数据类型

答案 3 :(得分:1)

关于p被分配而你没有随后打电话给delete[],你是对的。但是,正如您所观察到的那样,p也指向elem指向的内存:

double* p = new double[a.sz]; // allocate memory
delete[] elem; // delete the old memory
elem = p; // point to the new memory allocated

正如其他人所指出的那样,elem会在析构函数中被删除。

没有复制构造函数调用,因为没有复制:指针elem只是在指向它所指向的位置。