【发布时间】:2020-06-27 13:29:55
【问题描述】:
我的析构函数有问题。我有两个课程:地图和瓷砖。它们看起来像这样: (如果下面的代码片段还不够,我将在这个项目中添加 github,其中包含完整的代码: https://github.com/TMalicki/PathFinder-algorithms)
class Tile
{
private:
Tile* parent;
...
public:
Tile(sf::Vector2f size = { 50.f ,50.f });
Tile(const Tile& cTile);
Tile& operator=(const Tile& aTile);
~Tile();
...
}
和
class Map
{
private:
vector<Tile*> board;
...
public:
Map(sf::Vector2i numberOfTiles = { 10, 10 }, sf::Vector2f sizeOfTiles = {
50.f, 50.f });
Map(const Map& cMap);
Map& operator=(const Map& aMap);
~Map();
...
}
它们的析构函数看起来像这样:
Tile::~Tile()
{
if (parent != nullptr)
{
delete parent;
parent = nullptr;
}
}
Map::~Map()
{
for (int i = 0; i < board.size(); i++)
{
delete board[i];
board[i] = nullptr;
}
}
代码用于最短路径搜索算法。我必须存储以前的 Tile,所以当算法找到完成时,它可以向后搜索最短路径。如果需要,我可以添加更多代码。总结一下:地图对象有瓷砖的矢量。每个 Tile 首先没有指向任何东西。但是如果它被算法使用而不是前一个的确切 Tile 存储位置,依此类推到开始。我知道智能指针可以帮助我,但我认为首先学习如何做到这一点对我有好处,也许更难。 我认为问题在于(我不知道为什么)在使用 Tiles 删除 Map 矢量时,我不仅删除了确切的 Tile,而且还以某种方式删除了该 Tile 的父级 Tile?和 f.e.在下一次迭代中,当它应该删除上一次迭代的父级时,它不能因为它已经被删除。我认为在 Tile 析构函数中的 if 语句之后,如果它已经是,它不会被延迟。但这没有帮助。
从调试器模式我有这个:
在从调试器模式进行分析期间,我开始认为精确图块的析构函数首先删除父图块,然后是他自己。之后它跳转到 Tile 析构函数中的 parent = nullptr 行。但不知何故,只有子 Tile 被设置为 nullptr。
【问题讨论】:
-
Map object has vector of Tiles.-- 不,它没有。它的向量是Tile *,而不是Tile。为什么不是简单的vector<Tile>?如果指针在对象之间共享,那么 C++ 中有一个叫做std::shared_ptr的东西,而不是使用原始指针。 -
#PaulMcKenzie 是的,我知道智能指针,但我认为它有助于我更好地理解该主题。所以我试图在那个项目中避免使用智能指针。还有......是的,我的意思是
Tile*。我使用了Tile*,因为我想从Map类对象更改Tile对象的一些属性。 -
您正在到处删除
Tile *,而没有一个连贯的策略来确定谁是所有者。您将在 Map 析构函数中删除Tile *,同时也在 Tile 析构函数(父级)中删除Tile *。谁拥有什么?您不能两次删除相同的内存地址。这正是共享指针解决的问题——如果您知道两个或多个实体将共享一个指针,而最后一个使用它的实体是指向delete指针的最后一个,那么这就是 shared_ptr用于。
标签: c++ pointers sfml destructor path-finding