如何删除带有指向其他对象的指针的动态对象数组 (C++)
How to delete a dynamic array of objects with pointers to other objects (C++)
长话短说,我必须使用 C++ 中的线性散列为大学编写一个散列 table。哈希 table 有效,但资源没有被释放,这是一个问题,尤其是单元测试测试 table 具有 100k+ 值并且留下的垃圾非常大。
基本上当我创建新的散列table时,我正在做以下事情:
hashTable = new Bucket[this->tableSize];
for (size_t i = 0; i < tableSize; i++) {
hashTable[i] = * new Bucket();
}
每个 Bucket 都可以包含一个指向另一个溢出桶的指针,可以设置也可以不设置。
class Bucket {
private:
size_t bucketSize;
size_t elementsInBucket;
E v[N]; // int v[N];
bool hasOverflow;
Bucket * nextBucket = nullptr;
我的问题是,我怎样才能删除整个散列table,包括带有潜在溢出桶的桶,因为下面只释放了一半占用的内存。
delete[] hashTable;
hashTable = nullptr;
谢谢!
你马上就在这行漏了一个 Bucket
:
hashTable[i] = * new Bucket();
它的作用是:
- 分配一个新的
Bucket
和 return 指向它的指针
- 取消引用 returned 指针并将对新
Bucket
的引用传递给 Bucket::operator=
- 将空的
Bucket
复制到已经存在的对象hashTable[i]
- 丢弃指向您新分配的
Bucket
的指针,从而泄漏它
hashTable
是指向 tableSize
Bucket
数组的第一个元素的指针。这些对象已经存在,因此您无需在循环中分配新对象。
此外,您没有显示 Bucket
的析构函数,也没有显示您如何分配 Bucket::nextBucket
。我假设每个 Bucket
都应该拥有它的 nextBucket
,所以你应该有一个析构函数来做类似
的事情
Bucket::~Bucket()
{
delete nextBucket;
}
除非我记错了,下面这行代码是内存泄漏:
hashTable[i] = * new Bucket();
您在这里所做的是在堆上分配一个新的 Bucket 对象,然后立即按值将其复制到您的数组中。你用new创建的指针超出作用域,堆上原来的Bucket就泄露了。您剩下的是您刚刚在堆中分配并泄漏的内容的 copy。
相反,您应该将指针存储在数组中:
hashTable = new *Bucket[this->tableSize];
for (size_t i = 0; i < tableSize; i++) {
hashTable[i] = new Bucket();
}
并删除它:
for (size_t i = 0; i < tableSize; i++) {
delete hashTable[i];
hashTable[i] = nullptr;
}
delete[] hashTable;
hashTable = nullptr;
您还应该确保您的析构函数删除了成员指针,这样当您在每个 Bucket 指针上调用 delete 时,嵌套的内存就会被释放:
~Bucket() {
delete nextBucket;
nextBucket = nullptr;
}
最后,您需要更改任何执行此操作的代码:
hashTable[i].something
对此:
hashTable[i]->something
在我看来,这是处理动态数组的正确方法。
长话短说,我必须使用 C++ 中的线性散列为大学编写一个散列 table。哈希 table 有效,但资源没有被释放,这是一个问题,尤其是单元测试测试 table 具有 100k+ 值并且留下的垃圾非常大。 基本上当我创建新的散列table时,我正在做以下事情:
hashTable = new Bucket[this->tableSize];
for (size_t i = 0; i < tableSize; i++) {
hashTable[i] = * new Bucket();
}
每个 Bucket 都可以包含一个指向另一个溢出桶的指针,可以设置也可以不设置。
class Bucket {
private:
size_t bucketSize;
size_t elementsInBucket;
E v[N]; // int v[N];
bool hasOverflow;
Bucket * nextBucket = nullptr;
我的问题是,我怎样才能删除整个散列table,包括带有潜在溢出桶的桶,因为下面只释放了一半占用的内存。
delete[] hashTable;
hashTable = nullptr;
谢谢!
你马上就在这行漏了一个 Bucket
:
hashTable[i] = * new Bucket();
它的作用是:
- 分配一个新的
Bucket
和 return 指向它的指针 - 取消引用 returned 指针并将对新
Bucket
的引用传递给Bucket::operator=
- 将空的
Bucket
复制到已经存在的对象hashTable[i]
- 丢弃指向您新分配的
Bucket
的指针,从而泄漏它
hashTable
是指向 tableSize
Bucket
数组的第一个元素的指针。这些对象已经存在,因此您无需在循环中分配新对象。
此外,您没有显示 Bucket
的析构函数,也没有显示您如何分配 Bucket::nextBucket
。我假设每个 Bucket
都应该拥有它的 nextBucket
,所以你应该有一个析构函数来做类似
Bucket::~Bucket()
{
delete nextBucket;
}
除非我记错了,下面这行代码是内存泄漏:
hashTable[i] = * new Bucket();
您在这里所做的是在堆上分配一个新的 Bucket 对象,然后立即按值将其复制到您的数组中。你用new创建的指针超出作用域,堆上原来的Bucket就泄露了。您剩下的是您刚刚在堆中分配并泄漏的内容的 copy。
相反,您应该将指针存储在数组中:
hashTable = new *Bucket[this->tableSize];
for (size_t i = 0; i < tableSize; i++) {
hashTable[i] = new Bucket();
}
并删除它:
for (size_t i = 0; i < tableSize; i++) {
delete hashTable[i];
hashTable[i] = nullptr;
}
delete[] hashTable;
hashTable = nullptr;
您还应该确保您的析构函数删除了成员指针,这样当您在每个 Bucket 指针上调用 delete 时,嵌套的内存就会被释放:
~Bucket() {
delete nextBucket;
nextBucket = nullptr;
}
最后,您需要更改任何执行此操作的代码:
hashTable[i].something
对此:
hashTable[i]->something
在我看来,这是处理动态数组的正确方法。