题
假设我有一个hash_map和一个像
这样的代码// i is an iterator
i = hash_map.erase(i)
但是GCC的STL不会在擦除中返回迭代器,而是一个空白。现在是像
这样的代码hash_map.erase(i++)
安全(即不会使迭代器无效或做任何其他意外或不愉快的事情)?请注意这是一个hash_map。
解决方案
是的,这是安全的,因为在删除当前值之前, i
的值将被设置为下一个值。
根据有关散列容器的SGI文档,非非 - 删除元素,甚至不调整大小(没有关于插入是否会导致调整大小的说法,所以要小心我承认这是一种可能性)---但在后一种情况下,迭代顺序将会改变。但这不适用于此,除非您在遍历或其他事情期间不遗余力地调整容器大小。 : - )
其他提示
您可以封装擦除,为您使用的所有容器提供相同的界面:
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返回下一个项目的迭代器。这就是vector,deque和list的工作方式。
- c.erase返回void并且不会使下一个迭代器无效。这就是map,set和(non-stdlib)hash_map的工作方式。 醇>
在游行中讨厌下雨,但我不认为你的建议是安全的。
i ++是后增量运算符,这意味着在调用erase之后i递增。但擦除会使指向被擦除元素的所有迭代器无效。因此,当i增加时,它不再有效。
如果你很幸运,它可能会偶然正常工作,直到有一天它不再存在。
据我所知,除此之外没有办法解决这个问题:
// tmp and i are both iterators
tmp = i;
++i;
hash_map.erase(tmp);
不隶属于 StackOverflow