【问题标题】:2D array of pointers or heap objects指针或堆对象的二维数组
【发布时间】:2012-12-19 23:14:10
【问题描述】:

我有一个游戏,它有一个网格,它是一个 2D 数组。这个数组填充了一个信息结构。

struct GridCell
{
    uint mCellID;
    Vector2 mPosition;
    uint mLevel;
    int mCellType;
};

class Grid
{
public:
    Grid();
    ~Grid()

protected:
    // Heap
    GridCell[][] mGridCells;

    // Dynamic
    GridCell*[][] mGridCells;
};

请记住,内存中可以同时存在多个网格,并且这些网格单元的范围可以从非常小到非常大: 这更适合作为网格单元堆还是动态(指针)网格单元?

据我了解: 堆单元会占用大量内存 动态单元仍然会,但它将是指针,而不是整个结构。但是,这会导致内存碎片化吗?

我不确定哪一个最适合这种情况,而且我可能也不完全理解两者之间的区别。帮助?

【问题讨论】:

    标签: c++ arrays memory-management


    【解决方案1】:

    C++ 中的类型具有固定大小。您的GridCells 的范围从非常小到非常大是不正确的。他们将是其中之一。 sizeof(GridCell) 已修复。它们可能各自指向不同大小的对象,但这些对象不属于GridCell 的大小。

    无论哪种方式,您建议的两种方法都将在内存中拥有完全相同数量的GridCells,因此使用指针不会节省任何东西。事实上,动态分配的方法将使用更多内存,因为您还存储了指向每个单元格的指针。指针方法可以提高内存效率的唯一方法是使用单个GridCell 对象来表示Grid 中的多个单元格。也就是说,有些指针是相同的。

    这真正归结为哪个更易于管理,答案始终是“没有指针的方法”。这意味着您的Grid 对象将自动管理GridCells 的构造和销毁,而无需您关心它,从而帮助您避免内存泄漏。如果使用指针方法,则必须在Grid 的构造函数中循环遍历数组,为每个元素执行new GridCell()。您还需要在析构函数中执行相同的操作,在您动态分配的每个单元格上执行 delete。这是一种痛苦,尤其是在不必要的时候。

    在需要指针的情况下,智能指针更可取。

    此外,对固定大小的数组使用std::array<std::array<GridCell, N> M> 可能会更好。它为您封装了数组,让您可以像使用标准库中的任何其他 Container 一样使用它。

    【讨论】:

      【解决方案2】:

      最好都不使用而使用std::vector。将您的二维数组设为 1d 并将值直接存储到向量中。或者如果你真的必须有二维,你可以创建一个向量的向量。

      【讨论】:

      • 这可能不是一个问题,但值得注意的是,如果向量的向量变得足够大并且需要相对频繁地迭代,它们可能会导致可怕的性能。数据的局部性可能很糟糕。一个更好的选择是一个大向量并手动计算子“数组”的偏移量。
      猜你喜欢
      • 1970-01-01
      • 2014-01-26
      • 2013-04-06
      • 2018-01-04
      • 1970-01-01
      • 1970-01-01
      • 2021-12-17
      • 2013-07-31
      相关资源
      最近更新 更多