C++ 如何从stl数据结构中删除反向迭代器?

C++ 如何从stl数据结构中删除反向迭代器?,c++,stl,iterator,C++,Stl,Iterator,由于某种原因,以下代码失败。不能简单地使用其base()方法擦除反向迭代器 #包括 #包括 int main() { std::一组信息; 一组插入物(1); 插入件(2); 一组插入物(3); std::set::reverse_iterator rev_iter=setofits.rbegin(); std::set::reverse_iterator nextRevIter=setofits.rbegin(); ++Nextite; while(rev_iter!=setofits.ren

由于某种原因,以下代码失败。不能简单地使用其base()方法擦除反向迭代器

#包括
#包括
int main()
{
std::一组信息;
一组插入物(1);
插入件(2);
一组插入物(3);
std::set::reverse_iterator rev_iter=setofits.rbegin();
std::set::reverse_iterator nextRevIter=setofits.rbegin();
++Nextite;
while(rev_iter!=setofits.rend())
{
//找到3并尝试删除
如果(*版本=3)
{
//这里的断层
擦除集合(rev_iter.base());
}
rev_iter=nextRevIter;
++奈斯特维特;
}
}
如何才能正确地做到上述几点?给定一个与要擦除的内容对应的反向迭代器,如何擦除它


注意,很遗憾,擦除不会使用反向迭代器。它需要真实的东西。

使用迭代器本身调用
erase
(无需使用
base

#包括
#包括
int main()
{
std::一组信息;
一组插入物(1);
插入件(2);
一组插入物(3);
std::set::reverse_iterator rev_iter=setofits.rbegin();
while(rev_iter!=setofits.rend())
{
//找到3并尝试删除
如果(*版本=3)
{
rev_iter=擦除设置(rev_iter);
}
其他的
{
++雷沃·伊特尔;
}
}
}

此外,您不需要单独的“下一个”迭代器(参见上面的更改)。更好的方法是使用
std::remove_if
(或类似的函数)。

显然,解决方案是base()返回的值为1。以下标识适用于反向迭代器:

&*(reverse_iterator(i)) == &*(i - 1) 
或者换句话说,反向迭代器总是一次通过作为其基础的常规迭代器。不知道为什么

在GCC中 简单地改变

        // SEGFAULT HERE
        setOfInts.erase( rev_iter.base());

我当然很好奇,为什么上面的身份是有意义的

在VisualStudio中 回到工作中,在VisualStudio中尝试这个方法,我发现上面的解决方案不太管用。“nextIter”在擦除时变为无效。相反,您需要从擦除中保存临时项以获得下一个迭代器,而不是像上面那样保留下一个迭代器

  set<int>::iterator tempIter = setOfInts.erase(--rev_iter.base());
  rev_iter = setOfInts.erase(tempIter);
迭代器tempIter=setofits.erase(--rev_iter.base()); rev_iter=擦除设置(临时设置); 因此,最终的解决方案是

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;
        }
    }   

}
intmain()
{
使用名称空间std;
一组信息;
一组插入物(1);
插入件(2);
一组插入物(3);
set::reverse_iterator rev_iter=setofits.rbegin();
while(rev_iter!=setofits.rend())
{
//找到3并尝试删除
如果(*版本=3)
{

cout当您使用反向迭代器进行迭代并希望使用base()修改其容器时,请始终记住,反向迭代器始终基于原始顺序的下一个迭代器。这有点不直观,但实际上使代码更简单:

#include <set>
int main()
{
    std::set<int> setOfInts;
    setOfInts.insert(1);
    setOfInts.insert(2);
    setOfInts.insert(3);

    typedef std::set<int>::reverse_iterator RevIter;

    RevIter rev_iter = setOfInts.rbegin();
    while (rev_iter != setOfInts.rend())
    {
        // Find 3 and try to erase
        if (*rev_iter == 3)
            setOfInts.erase(--rev_iter.base());

        ++rev_iter;
    }
}
使用的对象(顺序相反)与

1从中,我们知道它只需要
迭代器

2从中,我们知道
&*(反向迭代器(i))==&*(i–1)。

因此,您可以擦除(-r_v.base())以擦除由“r_v”(和“current-1”)指向的元素:


嗯,擦除不会使用反向迭代器,这是我生命中最后几个小时的总结:)我认为这是因为你可以将一个指针指向数组的末尾,但不能指向数组的开头。因此,如果.rend()==i,那么i.base()==.begin(),而不是.begin()-1(即UB)。因此它始终是一次性的,但在取消引用时,它返回*-->.base()上述标识是为了确保反向迭代器可以在所有标准位置工作,这些标准位置期望迭代器范围指定半开间隔[第一个,最后一个)。如果不是这样的话,反向迭代器在std algos中将是无用的,因为“end”将被取消引用,而“begin”将被跳过。是的,它也提供了一个关于这个问题的逻辑视图。如果你想一想,就像现在一样,基础完全从.end()到.begin(),而不是从--.end()到--.begin(),这不是范围内的精确反向迭代。std::set::erase返回迭代器的事实是Microsoft扩展。
  set<int>::iterator tempIter = setOfInts.erase(--rev_iter.base());
  rev_iter = setOfInts.erase(tempIter);
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;
        }
    }   

}
#include <set>
int main()
{
    std::set<int> setOfInts;
    setOfInts.insert(1);
    setOfInts.insert(2);
    setOfInts.insert(3);

    typedef std::set<int>::reverse_iterator RevIter;

    RevIter rev_iter = setOfInts.rbegin();
    while (rev_iter != setOfInts.rend())
    {
        // Find 3 and try to erase
        if (*rev_iter == 3)
            setOfInts.erase(--rev_iter.base());

        ++rev_iter;
    }
}
riValue = find(riEnd.base(), riBegin.base(), value);
iValue = find(riBegin, riEnd, value);
            r_v+1            r_v          r_v-1
           current-2      current-1      current