【问题标题】:c++ How to deallocate and delete a 2D array of pointers to objectsc ++如何释放和删除指向对象的二维指针数组
【发布时间】:2016-07-08 10:17:12
【问题描述】:

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

【问题讨论】:

  • std::vector&lt;std::vector&lt;std::unique_ptr&lt;Object&gt; &gt; &gt; vector_of_objects;
  • 您注意二维对象数组还是二维指针数组?
  • @R Sahu:它是一个指向基类对象的二维指针数组,以这种方式设置以利用各种元胞自动机派生对象的多态行为。
  • @Chris 您对matrix_0[i] 数据的分配在哪里?您甚至没有正确进行分配(或者充其量是不完整的)。另外,如果数组在设置后没有改变形状,这在效率方面要好得多:stackoverflow.com/questions/21943621/… 只需使用Base* 作为数据类型。
  • @Paul,是的,你是对的,我忽略了那部分,因为对象本身有一个单独的内存取消分配任务,并且似乎与这个问题没有密切关系。

标签: c++ arrays pointers


【解决方案1】:

在这方面你有大量的删除工作要做:

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,因为删除后它们就消失了。

这是可怕的和不必要的。 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&lt;std::vector&lt;std::unique_ptr&lt;Object&gt;&gt;&gt; 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 的指针和几个用于标记结束的指针和最后使用的位置的位置。访问数据数组与访问使用new 制作的动态数组没有什么不同。使用索引运算符 [] 编译为 data_pointer + index 与在数组上使用 [] 完全相同。 Java的Vector中没有同步之类的东西。这只是简单的原始数学。

与动态数组相比,所有预先分配的 vector 都会花费两个指针的内存,而作为回报,您几乎不会遇到任何内存管理问题。

【讨论】:

  • 是的,可怕但有必要,我被告知,“速度”问题。感谢您提供及时且正确(经过测试)的答案。
  • 如果您在构建向量时保留足够的空间,这与std::vector&lt;std::vector&lt;Object*&gt;&gt; 之间的速度差异可能介于“无法检测”和“可忽略不计”之间。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 2013-07-31
    • 2021-01-20
    • 2014-01-26
    • 2021-08-23
    • 1970-01-01
    相关资源
    最近更新 更多