C++ 正确销毁 std::map 中的指针
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19970531/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Properly destroying pointers in an std::map
提问by Mike
I have a map declared as
我有一张地图声明为
std::map<std::string, Texture*> textureMap;
which I use for pairing the path to a texture file to the actual texture so I can reference the texture by the path without loading the same texture a bunch of times for individual sprites. What I don't know how to do is properly destroy the textures in the destructor for the ResourceManager class (where the map is).
我用于将纹理文件的路径与实际纹理配对,这样我就可以通过路径引用纹理,而无需为单个精灵多次加载相同的纹理。我不知道该怎么做是在 ResourceManager 类(地图所在的位置)的析构函数中正确销毁纹理。
I thought about using a loop with an iterator like this:
我想过使用循环和这样的迭代器:
ResourceManager::~ResourceManager()
{
for(std::map<std::string, Texture*>::iterator itr = textureMap.begin(); itr != textureMap.end(); itr++)
{
delete (*itr);
}
}
But that doesn't work, it says delete expected a pointer. It's pretty late so I'm probably just missing something obvious, but I wanted to get this working before bed. So am I close or am I totally in the wrong direction with this?
但这不起作用,它说删除需要一个指针。现在已经很晚了,所以我可能只是遗漏了一些明显的东西,但我想在睡觉前完成这项工作。那么我是关闭还是完全错误的方向?
回答by Roger Rowland
As far as your sample code goes, you need to do this inside the loop:
就您的示例代码而言,您需要在循环内执行此操作:
delete itr->second;
The map has two elements and you need to delete the second. In your case, itr->first
is a std::string
and itr->second
is a Texture*
.
地图有两个元素,您需要删除第二个。在您的情况下,itr->first
is astd::string
和itr->second
is a Texture*
。
If you need to delete a particular entry, you could do something like this:
如果您需要删除特定条目,您可以执行以下操作:
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);
}
You have to make sure that the entry exists in the map otherwise you may get an exception when trying to delete the texture pointer.
您必须确保该条目存在于地图中,否则在尝试删除纹理指针时可能会出现异常。
An alternative might be to use std::shared_ptr
instead of a raw pointer, then you coulduse a simpler syntax for removing an item from the map and let the std::shared_ptr
handle the deletion of the underlying object when appropriate. That way, you can use erase()
with a key argument, like so:
另一种方法可能是使用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");
That will do two things:
这将做两件事:
- Remove the entry from the map, if it exists
- If there are no other references to the
Texture*
, the object will be deleted
- 从地图中删除条目(如果存在)
- 如果没有其他对 的引用,则
Texture*
该对象将被删除
In order to use std::shared_ptr
you'll either need a recent C++11 compiler, or Boost.
为了使用,std::shared_ptr
你需要一个最新的 C++11 编译器,或者Boost。
回答by charo
The answer didn't fully address the looping issue. At least Coverty (TM) doesn't allow erasing the iterator within the loop and still use it to continue looping. Anyway, after deleting the memory, calling clear() on the map should do the rest:
答案并没有完全解决循环问题。至少 Coverty (TM) 不允许擦除循环内的迭代器并仍然使用它来继续循环。无论如何,删除内存后,在地图上调用 clear() 应该完成剩下的工作:
ResourceManager::~ResourceManager()
{
for(std::map<std::string, Texture*>::iterator itr = textureMap.begin(); itr != textureMap.end(); itr++)
{
delete (itr->second);
}
textureMap.clear();
}
回答by user541686
You're not using the right tool for the job.
您没有使用正确的工具来完成这项工作。
Pointers should not "own" data.
指针不应该“拥有”数据。
Use boost::ptr_map<std::string, Texture>
instead.