2013-07-25 100 views
8

我正在使用std::map将字符串值映射到MyType *。我的地图声明如下所示:销毁具有指针值的地图的正确方法

map<string, MyType *> *my_map = new map<string, MyType>; 

my_map是我的一个类的私有成员变量。我的问题是我不确定如何摧毁地图。在删除地图时,我还想在地图中包含的所有MyType *上拨打delete。这是我目前的析构函数:

my_map->erase(my_map->begin(), my_map->end()); 
delete my_map; 

请问这个删除包含在地图上的指针,或者我需要调用抹去之前通过地图迭代删除每个指针?

+2

后面的'map'(以及标准库中的大多数(如果不是全部的话)容器)并没有被设计为在销毁时删除它包含的任何指针。 – Nbr44

+0

好的谢谢。我读到的文件不是很清楚。它是这样写的:“这样可以有效地减少容器的大小,删除的元素数量会被摧毁。” – Max

+3

这是一个常见的误解 - _pointers_本身确实被破坏,但是这并不会改变它指向的内存位置的状态。 – Nbr44

回答

9

指针只是指向。当使用原始指针时,您需要知道应用程序的哪个部分拥有指针指向的资源。如果它们属于地图,则在地图被销毁之前,您需要遍历地图并调用每个指针的delete。但是,如果地图只保存指向您的代码的其他部分所拥有的对象的指针,则不需要执行任何操作。

更安全的解决方案是使用shared_ptr来管理对象生存期,这将确保在最后一个shared_ptr被销毁时正确删除该对象。您可以将shared_ptrs存储在地图中,并且如果没有其他shared_ptr实例引用地图中的对象,则当地图被销毁时,对象将根据需要被销毁。

2

如果您使用smart pointers而不是原始指针,则会自动为您清理所有内容。

// header: 
using MapType = std::map<std::string, std::shared_ptr<MyType>>; 
shared_ptr<MapType> my_map; 

// usage: 
my_map.emplace("foo", std::make_shared<MyType>()); 

// destructor: 
MyClass::~MyClass() 
{ 
    // nothing! 
} 
3

请问这个删除包含在地图中的指针[...]

不,根据您提供的代码,您将泄漏地图的每个成员。

通常,每new必须有一个匹配delete。对于地图,您有一个delete,但对于地图中的元素没有。

这个问题的最正确的解决方案是根本不使用动态分配。只是存储MyType小号目录,如果可能的话:......和

map<string, MyType>

而不是自动动态分配map本身,店:

map<string,MyType> my_map; 

如果自动存储时间是不可能的一些原因,然后使用智能指针进行动态分配。给定一个C++编译器11,使用unique_ptr(或者很少,shared_ptr甚至weak_ptr)在map的元素:(给定一个C++编译器03,使用其升压当量)

map<string, unique_ptr<MyType>> my_map; 

那么当my_map被销毁时,所有元素将会是delete d。

霸菱这一切,如果你是在一个情况下没有上面会为你工作(我会被高度怀疑),那么你就需要遍历地图youself:

struct deleter 
{ 
    template <typename T> operator() (const T& rhs) const 
    { 
    delete rhs.second; 
    } 
}; 

for_each (my_map->begin(), my_map->end(), deleter()); 

在C++ 11,这可能是由拉姆达的东西沿着线:

for_each (my_map->begin(), my_map->end(), [](auto item) -> void 
{ 
    delete item.second; 
}); 
1

在现代C++,只要让你的生活更方便,使用指针只有如果严格要求。

您开始使用此代码:

map<string, MyType *> *my_map = new map<string, MyType>; 

你可以做的第一件事就是考虑使用std::map实例作为数据成员,而不是指针它。

然后,如果MyType不复制超贵及其实例仅由图资,只考虑从string简单mapMyType(而不是MyType*):

// my_map data member - no pointers --> automatically deleted in class destructor 
map<string, MyType> my_map; 

如果你真的需要包含指针的地图,考虑使用智能指针,如std::shared_ptr(可在C++ 11/14中获得)获取共享所有权,或者使用std::unique_ptr获取唯一的非共享所有权。
(如果你的目标C++ 98/03,一个选择是使用boost::shared_ptr由于没有移动语义,你不能有unique_ptr,这在很大程度上基于移动语义功能。)
例如:

// Map containing _smart_ pointers 
//  --> default destructor is fine (no need for custom delete code) 
map<string, shared_ptr<MyType>> my_map; 

正如可以看到的,使用值语义(而不是原始指针),或智能指针,可以简化代码并使用由C++提供的自动销毁