如何使用反向迭代器调用erase函数

237

我正在尝试做这样的事情:

for ( std::list< Cursor::Enum >::reverse_iterator i = m_CursorStack.rbegin(); i != m_CursorStack.rend(); ++i )
{
    if ( *i == pCursor )
    {
        m_CursorStack.erase( i );
        break;
    }
}

然而,erase接受的是正向迭代器而不是反向迭代器。是否有一种方法可以将反向迭代器转换为正向迭代器或另一种方法来从列表中删除该元素?


19
顺便提一下,当编写这种循环时,不要像你在i != m_CursorStack.rend()中所做的那样反复计算结束迭代器。相反,应该写成i = m_CursorStack.rbegin(), end = m_CursorStack.rend(); i != end;。也就是说,初始化一个您可以保留用于重复比较的迭代器--假设结束位置不会因循环体的副作用而改变。 - seh
在我看来,这里显而易见的问题是你为什么要这样做。通过反向遍历列表,你能得到什么好处?自己编写代码而不使用std::remove,你又能得到什么好处? - Jerry Coffin
4
我只想移除一个元素,因此需要删掉 'break;',使用 'remove' 会删除所有匹配的元素并且需要更长时间,而且不能实现我想要的效果。在这种情况下,我想要移除的元素几乎总是列表的最后一个或非常靠近它,因此反向迭代也更快且更适合解决这个问题。 - 0xC0DEFACE
4
这段话表明设计者没有具体定义实现,因为作为用户,你不需要知道或关心它,但是@seh却期望我们奇迹般地知道rend()是如何计算的并且非常耗费资源。 - stu
@JerryCoffin,从std::vector::erase()的规范中可以看出:“使得被删除点之后(包括end()迭代器)的所有迭代器和引用失效。”因此,如果您想要在向量中删除多个元素,可以从末尾开始迭代,一边删除一边前进,这样就不必担心迭代器失效的问题。 - user140327
显示剩余5条评论
14个回答

0

在金融业的限价订单簿管理中,试图消除地图背面的习语很常见。

档口询价单是最低询价,自然会排在地图开头。

档口竞价单是最高出价,自然会排在地图末尾。

我有点不确定是否要使用奇怪的std::next(i).base()

相反,如果该地图通常与反向迭代器一起使用,则将比较运算符更改为gt。大值将排在地图开头,然后可以使用普通迭代器--消除对擦除的反向迭代器调整的需要。


0

反向迭代器很难使用。所以只使用了普通的迭代器。'r' 它从最后一个元素开始。当找到要删除的元素时,删除它并返回下一个迭代器。例如,当删除第三个元素时,它将指向当前的第四个元素和新的第三个元素。因此,应该减少1来向左移动。

void remchar(string& s,char c)
{      
    auto r = s.end() - 1;
    while (r >= s.begin() && *r == c)
    {
        r = s.erase(r);
        r -= 1;
    }
}

-1
如果 m_CursorStack 是一个向量,你可以通过索引来删除:
m_CursorStack.erase(m_CursorStack.begin() + m_CursorStack.size() + int(m_CursorStack.rbegin() - i) - 1);

-1

在循环中使用 m_map.erase((++r_iter).base() 的原因是 erase() 会使 ++r_iter 失效!我们只需要使用 erase() 的返回值即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接