这两种释放2D阵列的方法是否相似?
int** M = new int*[5];
for (int i = 0; i < 5; ++i)
M[i] = new int[3];
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 3; ++j) {
M[i][j] = i + j;
}
}
删除我:
for (int i = 0; i < 5; ++i)
delete [] M[i];
delete [] M;
并删除II:
delete [] *M;
delete [] M;
这两个代码是否相同?
答案 0 :(得分:6)
delete [] *M;
与delete [] M[0]
相同,因此它不等同于删除循环中的所有M[i]
,因为只会删除第一个std::vector
。循环是避免内存泄漏的正确方法。
或者更好的是,使用{{1}}代替手动分配,您不必担心删除指针。
答案 1 :(得分:5)
他们并不相似。他们不相似的一个明显原因是你打电话new[]
6次,而在delete[]
的第二个版本,你打电话给“删除”2次。
delete [] *M;
delete [] M;
对于new[]
的每次通话,您都应该将其与delete[]
匹配,显然您没有这样做。
如果您希望这两个delete[]
的呼叫匹配,则必须更改分配2d阵列的方式。改变是这样的:
int** M = new int*[5];
int *pool = new int[5*3];
for (int i = 0; i < 5; ++i, pool += 3)
M[i] = pool;
在上面的示例中,仅对new[]
进行了2次调用,一次针对行指针,另一次针对内存池。然后循环只是将池中的每个行指针指向适当的位置。
现在,“2调用”delete[]
将正常工作,只要您在分配和解除分配数组之间不做任何奇怪的事情,例如损坏的内存。
以这种方式分配2d数组的优点是new[]
只被调用两次,无论列数如何。因此,如果您有10,000 x 10,000矩阵,则原始版本需要调用new[]
10,001次,而使用该池的上述版本只需要调用new[]
2次。这很可能会加速程序,因为分配器只被调用两次(然后再调用两次)。
此外,如果数组数据需要是连续的,则首选上述方法,以便可以使用简单的指针算法转到任何行或列。
但是,请确保:
否则维护以我描述的方式分配的矩阵变得更加困难。