如何删除带有指向其他对象的指针的动态对象数组 (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();

它的作用是:

  1. 分配一个新的 Bucket 和 return 指向它的指针
  2. 取消引用 returned 指针并将对新 Bucket 的引用传递给 Bucket::operator=
  3. 将空的Bucket复制到已经存在的对象hashTable[i]
  4. 丢弃指向您新分配的 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

在我看来,这是处理动态数组的正确方法。