地牢爬行游戏中Tile网格内可选Door对象的实现与引用相关技术疑问
地牢爬行游戏中Tile网格内可选Door对象的实现与引用相关技术疑问
你的思路方向是对的,但代码里有几个细节问题和可以优化的地方,下面针对你的问题逐一解答:
1. 这种可选对象的设计是否合理?内存占用是否可控?
用指针(或智能指针)存储可选的Door对象是非常合理的:
- 只有当Tile是门类型时,才会分配
Door的内存,非门Tile的doorHere只是一个指针(64位系统下占8字节),相比给每个Tile都嵌入完整Door对象(可能占16+字节),内存效率高很多。 - 按你说的1.5%的门概率,200x200的网格最多只会生成120个
Door对象,整体内存开销完全可控。
不过你的代码里有个类型不匹配的问题:你声明了Door* doorHere;,但用std::make_unique<Door>(...)赋值——make_unique返回的是std::unique_ptr<Door>,不能直接赋值给原始指针Door*。建议把doorHere改成std::unique_ptr<Door>,这样能自动管理内存,不用手动写析构函数清理,避免内存泄漏。
2. Main函数里的引用方式是否正确?->是否必须?
你的Main代码里有两处错误:
// 错误写法 char something = myDungeon.tiles[i][j]->doorHere.facingDir;
myDungeon.tiles[i][j]是Tile对象(不是指针),所以应该用.而非->访问它的成员;doorHere如果是指针/智能指针,访问其成员必须用->,不能直接用.。
修正后的正确写法(以std::unique_ptr<Door>为例):
// 先检查Door是否存在,避免空指针访问 if (myDungeon.tiles[i][j].doorHere) { char something = myDungeon.tiles[i][j].doorHere->facingDir; }
如果你不想反复写->,有两个替代方案:
- 如果你内存预算充足,可以直接在
Tile里嵌入Door对象,加一个标记判断是否为有效门:
这种方式可以用class Tile { public: char tileType; Door doorHere; bool isDoor = false; // 标记是否是有效门 // ...其他字段 };.访问doorHere的成员,但每个Tile都会占用Door的内存,适合小体量的Door结构。 - 对智能指针解引用后用
.:
但这种写法比char something = (*myDungeon.tiles[i][j].doorHere).facingDir;->更繁琐,不推荐。
3. 析构函数与内存释放问题
- 如果你用
std::unique_ptr<Door>作为doorHere的类型:Tile的析构函数不需要做任何额外操作,unique_ptr会在Tile被销毁时自动释放Door的内存;Dungeon里的Tile[200][200] tiles;是静态数组,当Dungeon对象被销毁时,所有Tile会自动销毁,对应的unique_ptr也会清理Door内存,完全不用手动干预。
- 如果你坚持用原始指针
Door* doorHere;:- 必须在
Tile的析构函数里手动delete doorHere;,否则会内存泄漏; - 如果
tiles是用malloc分配的动态数组,你需要在Dungeon的析构函数里循环遍历每个Tile,先delete tiles[i][j].doorHere;,再释放Tile的内存,最后释放整个tiles数组。
- 必须在
4. 如何检查Tile是否存在Door?
对于没有创建Door的Tile,doorHere会是nullptr(原始指针)或空的unique_ptr,检查方式很简单:
- 原始指针:
if (myDungeon.tiles[i][j].doorHere != nullptr) { // 存在Door,可以访问其成员 } - 智能指针
std::unique_ptr<Door>:
也可以结合if (myDungeon.tiles[i][j].doorHere) { // 存在Door,可以访问其成员 }tileType == 'D'来判断,但同时检查指针是否为空更安全,避免逻辑错误(比如不小心把tileType设为'D'但没分配Door)。
修正后的核心代码示例
#include <memory> struct Door { char facingDir; int doorState; // 构造函数简化初始化 Door(char dir, int state) : facingDir(dir), doorState(state) {} }; class Tile { public: int x; int y; char tileType; // 'F'=地板, 'W'=墙, 'D'=门 std::unique_ptr<Door> doorHere; // 用智能指针自动管理内存 }; class Dungeon { public: Tile tiles[200][200]; void drawDungeon() { // 迷宫生成逻辑,设置每个Tile的类型 for (int i = 0; i < 200; ++i) { for (int j = 0; j < 200; ++j) { // 假设这里有随机判断是否生成门的逻辑 if (tiles[i][j].tileType == 'D') { // 分配Door对象,智能指针自动接管内存 tiles[i][j].doorHere = std::make_unique<Door>('N', 4); } } } } }; Dungeon myDungeon; int main() { int i = 10, j = 10; // 示例坐标 if (myDungeon.tiles[i][j].doorHere) { char doorDir = myDungeon.tiles[i][j].doorHere->facingDir; // 使用doorDir执行后续操作 } return 0; }
内容来源于stack exchange
相关产品推荐
相关产品推荐

