在SO问题[如何在C ++中分配2D指针数组] [1],接受的答案还记录了如何解除分配和删除所述数组的正确程序,即"小心以正确的顺序单独删除包含的指针,行数组和列数组。"所以,我已经成功地在细胞自动机模拟程序中使用这个2D阵列。但是,我不能让这个数组的内存管理正确。除了上面的参考文献之外,我没有看到如何做到这一点的答案。
我按如下方式分配2D数组:
Object*** matrix_0 = new Object**[rows];
for (int i = 0; i < rows; i++) {
matrix_0[i] = new Object*[cols];
}
我徒劳地尝试(根据Valgrind)正确地取消分配上面的数组如下:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix_0[i][j] = NULL;
}
}
delete [] matrix_0;
matrix_0 = NULL;
显然,我错过了行和列部分作为参考[1]建议。你能告诉我我错过了什么吗?提前谢谢。
[1] :( 2009年11月20日)How to allocate a 2D array of pointers in C++
答案 0 :(得分:5)
你有很多要删除的内容:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
delete matrix_0[i][j]; // delete stored pointer
}
delete[] matrix_0[i]; // delete sub array
}
delete [] matrix_0; //delete outer array
matrix_0 = NULL;
除了NULL
之外,没有必要matrix_0
,因为它们在删除后消失了。
这太可怕了,没必要。 Use a std::vector
并认真重新考虑指向所包含对象的指针。
std::vector<std::vector<Object*>> matrix_0(rows, std::vector<Object*>(cols));
获取所需内容并将删除工作减少到
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
delete matrix_0[i][j]; // delete stored pointer
}
}
但SergeyA建议存储unique_ptr
,std::vector<std::vector<std::unique_ptr<Object>>> matrix_0;
减少了对0所需的删除。
由于速度是OP的目标之一,还有一个改进:
std::vector<std::unique_ptr<Object>> matrix_0(rows * cols);
访问是
matrix_0[row * cols + col];
对于当前在幕后进行的不可见数学和指针解引,这会进行一些可见的数学运算。重要的部分是向量现在存储为一个很好的连续内存块,增加了空间局部性并减少了缓存未命中数。对Objects
分散在整个记忆中的指针所导致的失误无能为力,但你不能总是赢。
关于vector
vs阵列的说明。一旦构建vector
,在这种情况下,这一切都在这里完成:
std::vector<std::unique_ptr<Object>> matrix_0(rows * cols);
所有vector
是指向一个和一对其他指针的指针,用于标记结尾和最后使用位置的位置。访问数据阵列与访问使用new
创建的动态数组没有什么不同。使用索引运算符[]
编译为data_pointer + index
与在数组上使用[]
完全相同。 Java的Vector中没有同步等。这只是简单的原始数学。
与动态数组相比,所有预先分配的vector
成本都是两个指针值的内存,作为回报,你可能会看到几乎没有内存管理问题。
答案 1 :(得分:0)
在设置指向NULL
的指针之前,您应首先delete
。删除列中的每个指针后,您可以delete[]
该行并将其设置为NULL
,因为每个元素都会被删除并消失。