我有两个问题。首先,我有一个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
这不起作用,那么这样做的正确方法是什么?我所要求的要求使我无法更改Object
或unordered_map
的设置方式。
答案 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
析构函数。