我与同事讨论了如何删除地图中的条目 地图将int作为索引,指针指向对象。
我说,首先释放该对象,然后删除该条目。 我的同事说先删除条目然后释放对象。那么最好的方法是什么?这个问题的任何技巧?
答案 0 :(得分:5)
首先删除对象,然后从地图中删除。否则你只是引入了一个无意义的中间变量来存储指针。只要您是单线程的,或者在多线程场景中具有适当的锁定,这两种方法就可以用于所有实用目的。
map<int, A *>::iterator it = mymap.find(1);
if (it != mymap.end()) {
delete it->second;
mymap.erase(it);
}
答案 1 :(得分:3)
除非您拥有多线程环境,否则无论哪种方式都可行。经验法则是,一旦你的函数返回,就不会有悬空指针,即没有指向刚被删除的对象的指针。
唯一可能出现的问题是,如果您先删除条目,则必须确保指针的临时副本,因为在删除条目后您将无法从地图中检索它
答案 2 :(得分:1)
受@Nim的启发,第三种方式如何:通过值或智能指针将对象存储在地图中。然后RAII将自动为您完成所有清理工作!
如果必须使用原始指针,那么只要确保应用线程问题所需的任何锁定,它就没关系。
答案 3 :(得分:1)
保守的方法是首先擦除,然后删除指针。
在标准容器中存储无效指针值可能会导致未定义的行为,至少根据C ++标准段落 [basic.stc.dynamic.deallocation] /的常见解释4 ,禁止使用无效指针值(例如内部复制指针的容器)和 [lib.container.requirements] ,它强制存储的对象容器必须是 CopyConstructible 和可分配。
然而,这个问题有点引起争议。
答案 4 :(得分:0)
这可能没关系。
如果你有两个线程,一个试图从地图中删除一个项目而另一个试图访问同一个地图,你可能会认为这很重要。您可能会得出结论,首先从地图中删除项目会更安全,以便其他线程不会检索指向已删除对象的指针。
但是,如果您有多个线程访问同一个映射,则需要使用同步对象(如果您使用的是普通Win32,则为互斥锁或CRITICAL_SECTION)来保护它.std :: map对于非同步多个不安全-threaded use,其中一个线程正在修改集合。因此,如果你在移除和删除时已经锁定了地图,那么你做这件事的方式无关紧要。
这样说,如果对象的破坏需要很长时间,您可能希望将删除调用移到代码的互斥锁定部分之外。在这种情况下,首先将对象的指针存储在临时变量中,在地图中删除其条目,解锁,然后删除。
答案 5 :(得分:0)
你应该考虑使用boost中的ptr_map。您没有理由为此汇总自己的解决方案。请倾听所有指出通过多线程访问容器的警告的人。