8

我正在使用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;

这会删除地图中包含的指针,还是我需要在调用擦除之前遍历地图以删除每个指针?

4

4 回答 4

9

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

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

于 2013-07-25T14:54:40.050 回答
4

如果你使用智能指针而不是原始指针,一切都会自动为你清理。

// 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!
}
于 2013-07-25T14:57:55.363 回答
4

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

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

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

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

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被销毁时,所有元素都将是deleted。

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

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;
});
于 2013-07-25T15:02:11.487 回答
2

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

您从以下代码开始:

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

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

然后,如果MyType复制成本不高且其实例仅由地图拥有,则只需考虑一个简单map的 from stringto 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,这在很大程度上基于移动语义功能。)
例如:

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

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

于 2013-07-25T15:12:23.590 回答