由于某种原因,以下代码失败.您不能简单地使用其base()方法擦除reverse_iterator.
#include#include int main() { std::set setOfInts; setOfInts.insert(1); setOfInts.insert(2); setOfInts.insert(3); std::set ::reverse_iterator rev_iter = setOfInts.rbegin(); std::set ::reverse_iterator nextRevIter = setOfInts.rbegin(); ++nextIter; while ( rev_iter != setOfInts.rend()) { // Find 3 and try to erase if (*rev_iter == 3) { // SEGFAULT HERE setOfInts.erase( rev_iter.base()); } rev_iter = nextRevIter; ++nextRevIter; } }
如何正确地做上述事情?如果reverse_iterator对应于您想要擦除的内容,那么如何删除它?
注意,遗憾的是不会使用reverse_iterator.它想要真实的东西.
显然,解决方案是base()返回1关闭.对于reverse_iterator,以下标识成立:
&*(reverse_iterator(i)) == &*(i - 1)
或者换句话说,reverse_iterator始终是一个通过它的基础的常规迭代器.不知道为什么.
在GCC简单地改变
// SEGFAULT HERE setOfInts.erase( rev_iter.base());
至
// WORKS! setOfInts.erase( --rev_iter.base());
我很清楚,为什么上面的身份才有意义.
在Visual Studio中回到工作中并在visual studio中尝试这个,我看到上面的解决方案并不是很有效.擦除时"nextIter"变为无效.相反,你需要将擦除中的临时值保存到下一个迭代器而不是保持像上面那样的nextIter.
set::iterator tempIter = setOfInts.erase(--rev_iter.base()); rev_iter = setOfInts.erase(tempIter);
所以最终的解决方案是
int main() { using namespace std; setsetOfInts; setOfInts.insert(1); setOfInts.insert(2); setOfInts.insert(3); set ::reverse_iterator rev_iter = setOfInts.rbegin(); while ( rev_iter != setOfInts.rend()) { // Find 3 and try to erase if (*rev_iter == 3) { cout << "Erasing : " << *rev_iter; set ::iterator tempIter = setOfInts.erase( --rev_iter.base()); rev_iter = set ::reverse_iterator(tempIter); } else { ++rev_iter; } } }
注意,关联容器不会从erase返回迭代器.因此,此解决方案不适用于地图,多图等.