4

我有一个

map<char,my_class*> mymap;

其中的内容如下。

mymap[0]=('a', 0x1);
mymap[1]=('b',0x2);
mymap[3]=('c',0x3);
mymap[4]=('d',0x1);

如您所见,我们对键“a”和“d”具有相同的值。我有一个 for 循环来删除地图中的指针。

for ( it=mymap.begin() ; it != mymap.end(); it++ ){
  delete it->second;
}

它崩溃是因为它试图删除 0x1 两次。我试着这样做

for ( it=mymap.begin() ; it != mymap.end(); it++ ){
  if(!it->second){
      delete it->second;
      it->second = NULL;
  }
}

即使这会尝试将指针设置为 NULL 两次,这会导致异常。删除地图中上述重复值的最佳方法是什么?

4

4 回答 4

5

NPE 的回答shared_ptr很好。但是如果你被迫使用真正的指针,我可能会这样做:

set<my_class*> values;
for (it=mymap.begin(); it != mymap.end(); it++)
{
  // insert.second will be false if the value is already in the set
  if (values.insert(it->second).second)
    delete it->second;
}

// Make sure you do something with mymap to ensure you don't double-delete later!
于 2012-12-18T10:18:20.750 回答
4

我的建议是保留shared_ptr<my_class>在您的地图中,并完全回避这个问题。

如果您不能这样做,您将需要保留一个辅助容器(例如 a set),其中包含您已经释放的指针。然后,您将在遍历地图时查阅并更新该容器。

于 2012-12-18T10:14:58.250 回答
2

如果您不想重复第二个条目,那么最好的解决方案可能是不插入它们开始。我能想到的最干净的解决方案是使用 Boost bimap。然而,我宁愿认为这种行为会让插入第二个条目的用户感到惊讶。

或者(假设您不能使用shared_ptr),解构地图时最简单的解决方案是创建一个std::set<MyClass*>包含所有元素的临时对象,然后从中删除。(std::set确保没有重复)。

虽然我在这里:您的第二个解决方案失败的原因不是因为您将指针设置为 null 两次;这没有什么问题。这是因为你有两个指向同一个对象的不同指针;将第一个设置为 null 不会修改第二个,因此您最终仍会尝试两次删除同一个对象。

于 2012-12-18T11:09:48.890 回答
0

如果您存储实例或使用智能指针会更简单。Std::Map 有自己的指向您的对象的内部指针,您可以通过依赖其他人对您的对象的句柄来避免头痛。该Boost库包含几个智能指针。如果您使用侵入式引用计数智能指针,那么当您的对象从地图中移除时,它可能会被自动销毁。

然后,您将能够使用擦除函数从映射中删除值,然后在调用析构函数链后删除您的对象(如果它是最后一个引用)。

于 2012-12-18T10:26:21.280 回答