在 SO 问题 [How to allocate a 2D array of pointers in C++] [1] 中,接受的答案还记录了如何取消分配和删除所述数组的正确过程,即“小心删除分别包含指针、行数组和列数组,并且顺序正确。”所以,我已经在元胞自动机模拟程序中成功地使用了这个二维数组。但是,我不能正确地管理这个数组的内存。除了上面的引用之外,我没有看到关于如何执行此操作的 SO 答案。
我按如下方式分配二维数组:
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++
最佳答案
你有大量的删除工作要做:
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];
这用一些可见的数学来换取目前在幕后进行的不可见的数学和指针取消引用。重要的部分是 vector 现在存储为一个很好的连续内存块,增加了空间局部性并减少了缓存未命中的次数。它无法解决由指向 Objects
的指针导致的未命中问题。分散在整个内存中,但你不能总是赢。
关于 vector
的注释与阵列。一次vector
已经建成,在这种情况下,它是一次性完成的:
std::vector<std::unique_ptr<Object>> matrix_0(rows * cols);
所有vector
is 是一个指向 an 的指针,还有几个其他指针指向标记结束和最后使用的位置的位置。访问数据数组与访问使用 new
生成的动态数组没有区别.使用索引运算符 []
编译为 data_pointer + index
与使用 []
完全相同在一个数组上。没有 Java 的 Vector 中的同步等。这只是简单的原始数学。
与动态数组相比,所有的预分配 vector
成本是两个指针的内存,作为返回,您几乎没有遇到内存管理问题。
关于c++如何释放和删除指向对象的二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36138946/