33

我有一张地图声明为

std::map<std::string, Texture*> textureMap;

我用它来将纹理文件的路径与实际纹理配对,这样我就可以通过路径引用纹理,而无需为单个精灵多次加载相同的纹理。我不知道如何正确销毁 ResourceManager 类的析构函数中的纹理(地图所在的位置)。

我考虑过使用带有这样的迭代器的循环:

ResourceManager::~ResourceManager()
{
    for(std::map<std::string, Texture*>::iterator itr = textureMap.begin(); itr != textureMap.end(); itr++)
    {
        delete (*itr);
    }
}

但这不起作用,它说 delete 需要一个指针。现在已经很晚了,所以我可能只是遗漏了一些明显的东西,但我想在睡前完成这项工作。那么我是接近还是我完全走错了方向?

4

3 回答 3

49

就您的示例代码而言,您需要在循环内执行此操作:

delete itr->second;

该地图有两个元素,您需要删除第二个元素。在您的情况下,itr->first是 astd::string并且itr->second是 a Texture*

如果您需要删除特定条目,您可以执行以下操作:

std::map<std::string, Texture*>::iterator itr = textureMap.find("some/path.png");
if (itr != textureMap.end())
{
    // found it - delete it
    delete itr->second;
    textureMap.erase(itr);
}

您必须确保该条目存在于地图中,否则在尝试删除纹理指针时可能会出现异常。

另一种方法可能是使用std::shared_ptr而不是原始指针,然后您可以使用更简单的语法从地图中删除项目,并std::shared_ptr在适当时让处理底层对象的删除。这样,您可以使用erase()key 参数,如下所示:

// map using shared_ptr
std::map<std::string, std::shared_ptr<Texture>> textureMap;

// ... delete an entry ...
textureMap.erase("some/path.png");

这将做两件事:

  • 从地图中删除条目(如果存在)
  • 如果没有其他对 的引用,则Texture*该对象将被删除

为了使用std::shared_ptr,您要么需要最新的 C++11 编译器,要么需要Boost

于 2013-11-14T05:54:10.190 回答
6

答案并没有完全解决循环问题。至少 Coverty (TM) 不允许擦除循环内的迭代器并仍然使用它来继续循环。无论如何,删除内存后,在地图上调用 clear() 应该完成剩下的工作:

ResourceManager::~ResourceManager()
{
    for(std::map<std::string, Texture*>::iterator itr = textureMap.begin(); itr != textureMap.end(); itr++)
    {
        delete (itr->second);
    }
    textureMap.clear();
}
于 2017-03-06T21:11:39.013 回答
0

你没有使用正确的工具来完成这项工作。

指针不应该“拥有”数据。

改为使用boost::ptr_map<std::string, Texture>

于 2013-11-14T08:09:32.327 回答