为什么在此复制分配 ctor 结束时没有释放获取的资源?
Why isn't the acquired resource released at the end of this copy assignment ctor?
我正在阅读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 不被视为内存泄漏?
我问这个是因为,到目前为止,我注意到对于每个新内容都必须删除,而我看到的问题说"我应该在此处使用删除吗",指出对于每个新内容,都应该删除。我看到这个问题 新的必须总是跟着删除吗?但在这种情况下,程序完成并释放资源,而在上面的代码中,程序继续。
(另外,还有一个附带的问题,elem = p 语句会调用复制赋值构造函数吗?这一行让我感到困惑,因为它似乎会调用它并执行一种无限循环(
对于执行的每个new
,应该在某个地方执行一个delete
。它不一定具有相同的功能。此外,程序文本中出现的一次delete
可能与几种不同的new
匹配,反之亦然。执行计数必须匹配,而不是文本匹配。
elem = p
什么都没叫。 elem
和p
是指针。这是一个内置的类型赋值。
一般模式是,如果一个类持有一个资源,那么它的析构函数将释放资源(参见 RAII(。所以,毫无疑问,有类似的东西
Vector::~Vector()
{
delete[] elem;
}
别处。
在对象生存期的不同点,其他操作可能会释放资源,例如,在这种情况下是复制赋值构造函数。如果这样做,那么资源将被仔细重新分配,或者将其设置为指示没有要释放的状态(例如,通过将其设置为 nullptr
(。
关于你的第二个问题。Vector
的复制赋值运算符只是为指针赋值 - 不涉及递归。
你说得对,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
只是更改它指向的位置。
您担心的delete
将在destructor
这种情况中完成。
代码所做的是为数据创建空间,复制数据并释放旧内存。将新内存留待以后处理,RAII
对于旁注:
elem = p
它不会调用class
的复制操作,因为它们是指向 POD 的指针,普通旧数据类型
- 原子获取是否与互斥锁释放同步?
- 负载是否可以在获取操作下方滑动/存储是否可以漂浮在C++释放上方?
- 多个线程之间的获取-释放内存顺序
- 螺纹 - 本地获取/释放同步
- 为什么此获取和释放内存围栏不能给出一致的值?
- 在C++中,获取/释放原子访问和结合围栏的放松访问之间有什么有效的区别吗
- 混合放松和释放获取内存顺序
- 获取释放内存顺序与顺序一致性不同的实际示例是什么?
- 如何在我的 c++ 代码中获取运行时的双重释放错误
- Python ctypes:如何释放内存?获取无效指针错误
- 使用std::mutex释放和获取
- 获取/释放内存订购
- C++11比较和交换获取/释放语义
- 获取/释放内存订购示例
- 是否存在获取或释放屏障自行发生而没有其他匹配障碍的情况
- 在x64上使用非临时存储获取/释放语义
- 为什么在此复制分配 ctor 结束时没有释放获取的资源?
- 使用获取-释放内存排序的传递同步
- 获取释放栅栏的意义不同平台的抽象指令实现
- 获取/释放通过[]操作符访问的原子变量的语义