c++ 如何解除分配和删除指向对象的指针的 2D 数组



在SO问题[如何在C++中分配指针的2D数组][1]中,公认的答案还记录了如何取消分配和删除所述数组的正确过程,即"小心删除包含的指针,行数组和列数组,并按正确的顺序单独删除。因此,我已经成功地在元胞自动机模拟程序中使用了这个2D阵列。 但是,我无法正确管理此阵列的内存。除了上面的参考之外,我没有看到有关如何执行此操作的 SO 答案。

我按如下方式分配 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日) 如何在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;

除了matrix_0之外,无需NULL任何内容,因为它们在删除后消失了。

这是可怕的和不必要的。使用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
    }
}

但是谢尔盖建议存储unique_ptrstd::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与数组的说明。一旦构建了vector,在这种情况下,它都可以在这里一次性完成:

std::vector<std::unique_ptr<Object>> matrix_0(rows * cols);

所有vector都是指向 an 的指针和其他几个指针,用于标记 end 和上次使用的位置。访问数据数组与访问使用 new 创建的动态数组没有什么不同。使用 index 运算符[]编译到与在数组上使用 [] 完全相同data_pointer + index。没有像Java的Vector那样的同步或类似的东西。这只是简单的原始数学。

与动态数组相比,所有预分配vector的成本都是两指针的内存,作为回报,您可以获得几乎看不到的内存管理问题。

在将指针设置为 NULL 之前,您应该先delete它们。删除列中的每个指针后,您可以delete[]行并将其设置为 NULL ,因为每个元素都将被删除并消失。

最新更新