为指向C++中的对象/对象的指针分配堆内存

Heap memory allocation for pointers to object/objects in C++

本文关键字:对象 指针 分配 内存 C++      更新时间:2023-10-16

我读了一本关于游戏中编程模式的书,并决定在不上课的时候给编写一个用于娱乐/练习的小引擎,这大量使用对象指针。

我创建了一个Tile类来表示地图的一个区域(位于标准 2D 坐标平原上,这是一个指向 Tile 对象的指针的 2D 数组(,该区域具有其他类型的对象(臭名昭著的瓷砖陷阱、角色和地面类型(,如下所示,其中包含指向切片对象将保存的数据的指针。

class Tile
{
public:
enum TileType{
WATER_DEEP,
WATER_SHALLOW,
GRASS,
MUD
};
Trap* getTileTrap();
GameObject* getTileObject();
TileType* getTileType();
Trap *tileTrap;
GameObject *tileObject;
TileType *tileType;
Tile();
virtual ~Tile();
protected:
private:
};

我好奇的是,保持其编写方式是否更有效率,内存/性能明智,让这个磁贴对象(在堆上分配(包含指向其他对象的指针,还是我应该废弃指针并简单地返回对象?

如果我保持它的编写方式,指针指向的对象是在堆上的其他地方创建的吗?它们是随机分配到某个地方,还是在创建 Tile 对象时与分配给 Tile 对象的空间一起分配?

保持

它的编写方式更有效,内存/性能明智,让这个平铺对象(在堆上分配(包含指向其他对象的指针,还是我应该废弃指针并简单地返回对象?

使用间接分配和动态分配几乎从未如此高效。只有当您存储的对象复制成本很高(例如,写入时复制字符串(时,它才会更有效。当您想要引用同一对象而不复制它时,它也是"必需的"。

tl;博士:

  • 首选,除非您有充分的理由引入间接寻址
  • 首选对指针的引用,因为它们没有"空状态"。

  • 考虑TileType:这是一个大小很可能小于或等于sizeof(void*)enum。通过将其存储为指针并通过指针返回,您一无所获并失去所有内容。

    如果通过指针存储它,这意味着您可能需要动态分配。每次访问它时,您都需要跳过一个指针。

  • 关于TrapGameObject:根据它们的大小以及您是否需要引用语义,您可能希望使用std::unique_ptrstd::shared_ptr来存储它们,并返回Trap&/GameObject&以允许访问。


如果我保持它的编写方式,指针指向的对象是在堆上的其他地方创建的吗?它们是随机分配到某个地方,还是在创建 Tile 对象时与分配给 Tile 对象的空间一起分配?

看来你需要读一本好C++书,了解指针和参考的基础知识。除非初始化指针,否则它们将具有垃圾值。

  1. 不应使用原始指针进行所有权。您应该使用智能指针。

  2. 除非有充分的理由,否则不应使用动态分配。

该指针在以下情况下很有用 您希望存储不会过期,并且具有创建它的函数或可以"共享"的函数。您可以将它们视为一种全局变量,只要您没有忘记指针或没有释放内存,就可以访问它。例如,您可以让一个Tile对象创建GameObject,而另一个Tile类型的对象共享指向同一GameObject的指针。但是指针不是对象,这意味着在Tile类的情况下,您需要分配堆上的所有成员,然后在适当的时候手动释放它们。

例如,我认为没有必要TileType* getTileType();因为在构造函数中,您必须调用new,然后在析构函数中delete为几乎不占用空间且不需要共享的成员tileType调用。

你应该熟悉指针是什么以及它的用途,它有它的用途,但也有它的局限性。一旦您意识到持有指针而不是变量的潜力,您将能够快速判断使用哪个,包括潜在的性能增益/惩罚。