删除std映射中的重复值

时间:2012-12-18 10:12:00

标签: c++ stl map

我有一个

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 个答案:

答案 0 :(得分: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!

答案 1 :(得分:4)

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

如果你不能这样做,你需要保留一个你已经解除分配的辅助容器(例如set)指针。然后,当您在地图上进行迭代时,您将咨询并更新该容器。

答案 2 :(得分:2)

如果您不想复制第二个条目,那么也许是 最好的解决方案是不要插入它们。该 我能想到的最干净的解决方案是使用 提升bimap。我宁愿认为这种行为会令人惊讶 但是,插入第二个条目的用户。

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

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

答案 3 :(得分:0)

如果您存储实例或使用了智能指针,那会更简单。 Std :: Map有自己的内部指针指向你的对象,你可以依靠别人对你的对象的处理来节省头痛。 Boost库包含几个智能指针。如果您使用侵入式引用计数smartpointer,那么当您的对象从地图中删除时,它可以自动销毁。

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