如何为 3D 矢量中未使用的元素释放内存?

Posted

技术标签:

【中文标题】如何为 3D 矢量中未使用的元素释放内存?【英文标题】:How can I free memory for unused elements in 3D vectors? 【发布时间】:2013-08-26 11:13:43 【问题描述】:

我生成了 100*100*500 向量(或者说是数组)。我随机填写元素。一些元素保持为空。我可以为未使用的元素释放内存吗?或者,向量数据结构已经做到了?

谢谢

【问题讨论】:

不,你不能,不,它没有。 你考虑过sparse matrix吗? 如果有许多未初始化的元素,您可以使用 std::map 或 std::unordered_map。或者,如果您的元素是重物并且您确实需要矢量,则可以对它们使用延迟初始化。 感谢您的建议 【参考方案1】:

您不能释放数组中单个元素占用的内存。数组作为连续的内存块分配和释放。您可能会考虑将数据存储在链接列表中,以完成该功能。如果您的问题是关于节省内存,我会想到稀疏向量。

编辑: 现在我们已经澄清(在评论部分)您的目标是存储并以图形方式表示一组给定的 3d 数据,我可以想出一个更详细的答案:

稀疏存储 3d 数据的常用方法是octree。为了与某种体素引擎一起使用,八叉树可以像这样轻松实现:

enum AtomType

    NoType,
    SolidType,
    StrangeType
;

class OctreeNode

    public:
        virtual OctreeNode* getSubNode(unsigned index) = 0;
        virtual AtomType getContent(void) = 0;
;

class OctreeBranchNode : public OctreeNode

    public:
        OctreeNode* getSubNode(unsigned index)
        
            if (subNodes) return subNodes[index]; else return nullptr;
        

        AtomType getContent(void)  return NoType; 

    private:
        OctreeNode** subNodes;
;

class OctreeAtomNode : public OctreeNode

    public:
        OctreeNode* getSubNode(unsigned index)  return nullptr; 

        AtomType getContent(void)  return content; 

    private:
        AtomType content;
;

关键是,您不需要以这种方式存储坐标,因为每个节点的 3d 位置从其在树层次结构中的位置是清晰的。

如果您想实际渲染您的数据集,您可能想尝试marching cubes 甚至将每个原子渲染为一个立方体(数据集是否足够大因此原子非常小并不重要) .还有一个很好的tutorial 讲述了如何编写基于 OpenGL 的体素引擎。

【讨论】:

是的,确实,稀疏向量听起来不错。你能推荐我一个好的学习资源吗? @kemalacikgoz 你想为教育目的编写自己的实现,还是介意使用库?无论如何,您可能想看看SparseLib。 Boost 还有一个sparseVector 实现。 我可以使用一个库 Rene R. ,非常感谢您的帮助。我真的很感激...... @kemalacikgoz 在这种情况下我会推荐 Boost uBLAS,vector_sparse.hpp 是其中的一部分。 好的,现在我将努力学习稀疏矩阵操作。我的意思是我将使用这个 3D 向量来存储使用 OpenGL 形成体积的盒子(立方体)的 3D 位置......(我的意思是,我近似一个 3D 结构,例如使用 tousands 或数百万个盒子的花瓶.) 比我可能需要通过 OpenGL 旋转或平移所有元素。【参考方案2】:

取决于您保存在数组中的元素的大小... 您可以使用指针数组并将所有元素设置为 nullptr/NULL。因此,您可以使用 new 运算符在堆上创建新元素。 但是如果元素和指针本身一样小,这种解决方案是没有意义的。

【讨论】:

我试图在另一个向量中列出二维网格。如果它是空的,我遵循一个循环来删除整个网格。这节省了近 20%。但仍然需要另一个计算循环。我确实想使用 C++ 的基本元素来做到这一点。其实我的问题就在这个链接里……请访问这个地址:opengl.org/discussion_boards/showthread.php/… 我敢说我会使用倒置的树形结构来表示金属毛刺。根是叶子在基础结构或“空气”中的末端。但这不是基本的 C++ 元素 是的,这似乎也很有希望。雷内给出了一个相当全面的答案。我会先尝试一下。等我有信心之后,我也可以试试这个!尼克,谢谢你的建议。【参考方案3】:

如果您使用std::vector,并且“100*100*500”表示“容量为 5000000 的向量”,请注意 std::vector 容器提供快速索引和直接数据访问,因为所有数据都存储在单个内存中堵塞。在 c++ 中你可以这样写:

int* arr = new int[5]; 
arr[0] = 1; 
arr[4] = 5;

在这个例子中,我们有一个容量为 5 的数组,但第一个、第二个和第三个元素仍未使用,但无法释放已分配但仍未使用的内存。您还可以创建一个容量为 2 的新数组,然后将所有元素复制到新数组,然后删除您的初始数组。以下是std::vector 的工作原理。在 c++11 中你也可以使用std::vector::shrink_to_fit(),但这并不能解决你的问题,因为std::vector::shrink_to_fit() 不会压缩数组,而只是从向量后面移除未使用的内存分配。

【讨论】:

感谢 Roman Chehowsky,这有助于我理解基础知识。我将尝试使用 Rene R. 建议的稀疏库。你认为稀疏库能解决我的问题吗? @kemalacikgoz 我没有看到你的问题,但我认为它会对你有所帮助。但在我看来,“提升”更好。 Boost 用于许多项目,因此您同时会获得经验。 谢谢大家...现在,至少我有了一个想法和一个可以遵循的方向...

以上是关于如何为 3D 矢量中未使用的元素释放内存?的主要内容,如果未能解决你的问题,请参考以下文章

如何为二维数组分配和释放堆内存?

释放 UIPageViewController 中未使用的页面

malloc内存分配

怎么用new定义一个类数组,并且释放内存

unity3d 资源加载与释放的内存管理

如何正确释放 ID3D11ShaderResourceView** 以避免内存泄漏?