为什么在动态数组上以特定方式调用'delete'不起作用?

时间:2011-09-27 22:51:39

标签: c++ memory-management dynamic-arrays

我想知道为什么这段代码不起作用:

void KeyValueList::Release()
{
//(m_ppKeyValueList is a dynamic array of pointers to objects on the heap)
    if (m_ppKeyValueList) {
        for (int i = 0; i < m_iCapacity; ++i) {
            if (m_ppKeyValueList[i]) {
                delete m_ppKeyValueList[i];
            }
        }
        /*delete[] m_ppKeyValueList;*/
        for (int i = 0; i < m_iCapacity; ++i) {
            delete (m_ppKeyValueList + i);
        }
    }
}

为什么我们不能以这种方式迭代动态数组和delete

4 个答案:

答案 0 :(得分:4)

动态数组不仅仅是一系列元素。它还包含有关数组大小的信息。此外,分配器只知道一个内存块。所以就像任何动态内存一样,你只能释放你分配的内容,而不是它的较小子集。

这就是为什么该语言要求您只对从delete[]表达式获取的指针调用new[],并且这是唯一方式来释放该内存。< / p>

答案 1 :(得分:3)

简单回答: 因为语言规范说您使用delete[]执行此操作。

更好的回答: 因为毕竟对于堆管理器而言m_ppKeyValueList指向的数组是一个大的分配,而不是m_iCapacity连续的小分配,所以你只需要告诉它分配的块开始的位置,并将它作为一个整体解除分配(如果需要,在调用单个析构函数之后);如果它将每个元素作为单个分离的分配保存到分配的块列表中,那将是一种愚蠢的资源浪费(如果它使用了位图,它可能没有足够的粒度来支持这种愚蠢的分配方案)。

答案 2 :(得分:0)

因为new int[5]分配了一个大小足以容纳5个整数的连续块。 new int 5次分配5个小块,每块大到足以容纳一个int。解除分配的数量必须等于分配的数量。

答案 3 :(得分:0)

案例1 m_ppKeyValueList是“指向堆上对象的动态指针数组” 在这种情况下,您需要逐个删除m_ppKeyValueList。如果这是你的意思,你的声明将是SomeType ** m_ppKeyValueList;你的分配和释放应该是

的形式

分配:

m_ppKeyValueList = new SomeType*[m_iCapacity];
for (int i = 0; i < m_iCapacity; ++i) {
  m_ppKeyValueList[ii] = new SomeType;
}

取消分配:

for (int i = 0; i < m_iCapacity; ++i) {
  delete m_ppKeyValueList[ii];
}
delete[] m_ppKeyValueList;

但是,您的代码失败表明您没有“指向堆上对象的动态指针数组。”

案例2 m_ppKeyValueList是堆上的动态对象数组 在这里,您的声明将采用SomeType * m_ppKeyValueList;形式,而不是逐个分配,您的分配和释放采用更简单的形式:

分配:

m_ppKeyValueList = new SomeType[m_iCapacity];

取消分配:

delete[] m_ppKeyValueList;

底线
您的分配和解除分配需要在数量和形式上相互匹配。如果您使用new分配内容,则需要使用delete销毁它。如果您使用new[]进行分配,则需要使用delete[]销毁它。