C++ 什么是非void STL擦除的安全等价物?
假设我有一个hash_映射和如下代码C++ 什么是非void STL擦除的安全等价物?,c++,stl,iterator,hashmap,C++,Stl,Iterator,Hashmap,假设我有一个hash_映射和如下代码 // i is an iterator i = hash_map.erase(i) hash_map.erase(i++) 但GCC的STL并没有以擦除的形式返回迭代器,而是一个空值。现在代码是什么样子的 // i is an iterator i = hash_map.erase(i) hash_map.erase(i++) 安全(即不会使迭代器无效或做任何其他意外或不愉快的事情)?请注意,这是一个哈希映射。是的,这是安全的,因为在删除当前值之前,
// i is an iterator
i = hash_map.erase(i)
hash_map.erase(i++)
但GCC的STL并没有以擦除的形式返回迭代器,而是一个空值。现在代码是什么样子的
// i is an iterator
i = hash_map.erase(i)
hash_map.erase(i++)
安全(即不会使迭代器无效或做任何其他意外或不愉快的事情)?请注意,这是一个哈希映射。是的,这是安全的,因为在删除当前值之前,
i
的值将被设置为下一个值
根据这一点,对于未擦除的元素,甚至对于大小调整,都不会发生无效(没有关于插入是否会导致大小调整的消息,所以要小心,我承认这是一种可能性)——但在后一种情况下,迭代顺序将被更改。但这不适用于此处,除非您在遍历或其他过程中特意调整容器的大小。:-) 我不想在游行上下雨,但我认为你的提议不安全 i++是后增量运算符,这意味着在调用擦除后i将递增。但是erase会使指向被擦除元素的所有迭代器失效。所以当我递增时,它就不再有效了 如果你幸运的话,它可能会意外地正常工作,直到有一天它不再工作 据我所知,没有办法解决这一问题,但类似于:
// 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、迭代器where){
返回c.erase(其中);
}
};
//专门处理返回类型void
模板
结构选择擦除{
模板
迭代器擦除(容器&c、迭代器where){
迭代器next(其中);
++其次;
c、 删除(何处);
下一步返回;
}
};
模板
选择擦除选择擦除(R(容器::*)(I)){
返回SelectErase();
}
}//名称空间详细信息
模板
迭代器擦除(容器&容器,迭代器,其中){
返回详细信息::选择擦除(&容器::擦除)。擦除(容器,其中);
}
这需要:
你能指出你在哪里读到的吗?对于ISO C++中定义的关联容器来说,这是正确的,但是我从来没有在SGI文档中读过类似的东西。我确实假设,对于该站点,除非另有特别说明,否则操作不会导致无效。请参阅(例如)其中提到的所有失效案例。(我选择vector是因为它是一种失效案例(似乎)比其他任何类型都多的数据类型。)根据标准,it++和it--(其中它是迭代器)相当于创建一个等于它的临时值,递减迭代器,返回临时值。是的,但是编译器可以在调用erase之前或之后自由调用(i++),因此如果编译器决定在erase之后调用(i++),那么i是无效的。Rodyland,你对此有什么引用吗?我从来没有听说过。我做了进一步的阅读,似乎我弄错了-编译器在调用erase之前被迫求值(I++),所以它是安全的。尽管如此,我还是不喜欢它。我同意这是一个不太安全的项目,但在这种情况下定义了增量运算符的使用。关于同一主题的更多信息: