从unordered_map C ++中删除键/值对

时间:2015-03-21 01:10:07

标签: c++ pointers c++11 dictionary

我有两个问题。首先,我有一个std::unordered_map<int,Object*>,其中Object看起来像这样:

// Object.hpp
class Object {
    public:
        Object();
        ~Object(){};
        int   Id();
        void setId(int i);
    private:
        int id;
};

unordered_map放在名为DataSet的类中,该类用作容纳所有这些对象的容器。在DataSet中,我希望能够从Object中给定一个整数id来正确删除一个键/值对。

为此,我尝试创建一个迭代器,通过id找到键,然后删除指向迭代器的指针,最后擦除键/值对。它看起来像这样:

int DataSet::deleteObject(int id)
{
    std::unordered_map<int,Object*>::iterator found_it = objects.find(id);
    if(found_it != objects.end()) {
        delete *found_it;
        objects.erase(found_it);
    }
    return 1;
}

然而,当我编译它时,我收到此错误:

dataset.cpp:44:9: error: cannot delete expression of type 'value_type'
      (aka 'pair<key_type, mapped_type>')
        delete *found_it;

是否有正确的方法可以删除该位置的Object

其次,在编写clear()方法时,我意识到我不能只做objects.clear(),所以我想知道是否有办法真正清除unordered_map

例如,当我使用std::vector时,我能够做到这一点:

std::vector<Object *>::reverse_iterator object;
for(object = objects.rbegin(); object < objects.rend(); object++)
    delete(*object);
objects.clear();

但是现在对于unordered_map这不起作用,那么这样做的正确方法是什么?我所要求的要求使我无法更改Objectunordered_map的设置方式。

2 个答案:

答案 0 :(得分:3)

问题的第一部分非常简单:迭代器引用值和类型为std::pair<int const, Object*>的给定位置。你不能delete这样的对象。您将使用对象的second部分获取指针,例如:

delete found_it->second;

然而,实际上这种维护非常罕见且容易出错。最好不要存储Object*而是存储std::unique_ptr<Object>std::unique_ptr<Object>会在销毁时自动释放对象。这也可以简化删除元素:

int DataSet::deletObject(int id) {
    return objects.erase(id);
}

当存储std::unique_ptr<Object>时,在将元素插入容器时可能需要更加冗长,例如:

objects.insert(std::make_pair(key, std::unique_ptr<Object>(ptr)));

鉴于你的Object类没有任何虚函数,你可以直接存储Object,但是:

std::unordered_map<int, Object> objects;

答案 1 :(得分:2)

取消引用unordered_map::iterator会产生unordered_map::value_type&,即pair<const Key, Value>&

你想要

delete found_it->second;
objects.erase(found_it);

退一步,您确定甚至需要std::unordered_map<int,Object*>代替std::unordered_map<int,Object>吗?如果您使用后者,则不必担心delete任何事情。

如果确实需要mapped_type成为Object*,则应使用std::unordered_map<int,std::unique_ptr<Object>>。同样,这使得在从地图中删除条目之前不必手动delete值。

此外,如果Object是您要添加到地图的任何类型的基类,请不要忘记它需要virtual析构函数。