正确销毁 std::map 中的指针

Properly destroying pointers in an std::map

本文关键字:map 指针 std      更新时间:2023-10-16

>我有一个地图声明为

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 itr->second;

地图有两个元素,您需要删除第二个元素。在您的情况下,itr->firststd::stringitr->secondTexture*

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

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()与键参数一起使用,如下所示:

// 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。

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

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

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

指针不应"拥有"数据。

请改用boost::ptr_map<std::string, Texture>