正确的方法来销毁具有指针值的地图

时间:2013-07-25 14:50:14

标签: c++ pointers stl

我正在使用std::map将字符串值映射到MyType *。我的地图声明如下所示:

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

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

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

这会删除地图中包含的指针,还是需要在调用erase之前迭代地图以删除每个指针?

4 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:3)

如果您使用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!
}

答案 2 :(得分:3)

  

这会删除地图[...]中包含的指针吗?

不,鉴于您提供的代码,您将泄露地图的每个成员。

通常,对于每个new,必须有匹配的delete。地图有delete,但是。

中的元素没有。{/ 1}

此问题的最正确解决方案是根本不使用动态分配。如果可能,只需存储MyType目录:

map<string, MyType>

...而不是动态分配map本身,而是自动存储:

map<string,MyType> my_map;

如果由于某种原因无法实现自动存储持续时间,则使用智能指针进行动态分配。给定C ++ 11编译器,对unique_ptr中的元素使用shared_ptr(或很少,weak_ptr或甚至map):

map<string, unique_ptr<MyType>> my_map;

(给定一个C ++ 03编译器,使用它的Boost等价物。)然后当my_map被销毁时,所有元素都将是delete d。

所有这一切,如果你处于上述任何一种都不适合你的情况下(我会非常怀疑),那么你需要自己迭代地图:

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

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

在C ++ 11中,这可以成为一个lambda,类似于:

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

答案 3 :(得分:2)

在现代C ++中,如果严格要求,只需让您的生活更轻松,只使用指针

您开始使用此代码:

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

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

然后,如果复制MyType并不是非常昂贵且其实例仅由地图拥有,那么只需考虑从mapstring的简单MyType(而不是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,这很大程度上取决于移动语义特性。 )
e.g:

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

如您所见,使用值语义(而不是原始指针)或智能指针,您可以简化代码并使用自动销毁< / strong>由C ++提供。