c ++如何释放和删除指向对象的二维指针数组

时间:2016-03-21 18:31:31

标签: c++ arrays pointers

在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++

2 个答案:

答案 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_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 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,因为每个元素都会被删除并消失。