我想知道为什么这段代码不起作用:
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
?
答案 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[]
销毁它。