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