什么是非无效STL擦除的安全等价物?
问题描述:
假设我有一个的hash_map和像什么是非无效STL擦除的安全等价物?
// i is an iterator
i = hash_map.erase(i)
一个代码,但GCC的STL不擦除返回迭代器,而是一个空白。现在就像是
hash_map.erase(i++)
安全代码(即不坏的迭代器或是否有任何其他意外或不愉快的事情)?请注意这是一个hash_map。
答
是的,这是安全的,因为i
的值将被设置为下一个值,在当前值被删除之前。
根据SGI documentation about hashed containers对于未擦除的元素,甚至对于调整大小(关于是否插入导致调整大小,所以要小心,我承认这是可能性)没有发生无效,但是在后一种情况下,迭代顺序将被改变。但是这并不适用于这里,除非你在遍历期间或者其他方面调整容器的大小。 :-)
答
讨厌游行的雨,但我不认为你的建议是安全的。
i ++是后增加的运算符,这意味着在擦除调用之后i增加。但擦除将使所有指向被擦除元素的迭代器无效。所以,当我增加时,它不再有效。
如果幸运的话,它可能会正常工作,直到有一天它不再有任何问题。
据我所知是没有办法解决这一点,但这样的:
// tmp and i are both iterators
tmp = i;
++i;
hash_map.erase(tmp);
答
您可以封装擦除提供相同的接口,让使用所有容器:
namespace detail {
template<typename Container, typename R>
struct SelectErase {
// by default, assume the next iterator is returned
template<typename Iterator>
Iterator erase(Container& c, Iterator where) {
return c.erase(where);
}
};
// specialize on return type void
template<typename Container>
struct SelectErase<Container, void> {
template<typename Iterator>
Iterator erase(Container& c, Iterator where) {
Iterator next (where);
++next;
c.erase(where);
return next;
}
};
template<typename I, typename Container, typename R>
SelectErase<Container,R> select_erase(R (Container::*)(I)) {
return SelectErase<Container,R>();
}
} // namespace detail
template<typename Container, typename Iterator>
Iterator erase(Container& container, Iterator where) {
return detail::select_erase<Iterator>(&Container::erase).erase(container, where);
}
这要求:
- c.erase返回的下一个项目的迭代器。这就是矢量,出列和列表的工作方式。
- c.erase返回void并且不会使下一个迭代器失效。这就是map,set和(non-stdlib)hash_map的工作方式。
你能指出你阅读的地方吗?在ISO C++中定义的关联容器是这样的,但我从来没有在SGI文档中读过类似的东西。 – PierreBdR 2008-10-20 10:31:09
它在我的文章链接到的页面上。我确实假设,除非另有特别说明,否则操作不会导致失效。请参阅http://www.sgi.com/tech/stl/Vector.html(例如)提及所有无效案例的地方。 – 2008-10-20 12:52:56