我正在阅读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语句是否会调用复制赋值构造函数?这行混淆了我,因为它似乎会调用它并进行一种无限循环)
答案 0 :(得分:2)
一般模式是,如果一个类拥有一个资源,那么它的析构函数将释放资源(参见RAII)。所以,毫无疑问,有类似
的东西Vector::~Vector()
{
delete[] elem;
}
其他地方。
在对象生命周期的各个点,其他操作可能会释放资源,例如,在这种情况下,复制赋值构造函数。如果这样做,那么资源将被小心地重新分配,或者它将被设置为指示没有任何东西要释放的状态(例如,通过将其设置为nullptr
)。
关于你的第二个问题。 Vector
的复制赋值运算符只是为指针分配一个新值 - 涉及 no 递归。
答案 1 :(得分:2)
对于每个被执行的new
,应该有一个delete
某个地方被执行。它不一定应该在同一个功能中。此外,程序文本中出现一次delete
可能会匹配new
的几种不同事件,反之亦然。执行计数必须匹配,而不是文本事件。
elem = p
不会打电话给任何人。 elem
和p
是指针。它是内置的类型分配。
答案 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
只是在指向它所指向的位置。