我正在尝试这样做:

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需要一个迭代器,而不是反向迭代器。有没有一种方法可以将反向迭代器转换为常规迭代器,或者另一种方法可以从列表中删除该元素?


当前回答

typedef std::map<size_t, some_class*> TMap;
TMap Map;
.......

for( TMap::const_reverse_iterator It = Map.rbegin(), end = Map.rend(); It != end; It++ )
{
    TMap::const_iterator Obsolete = It.base();   // conversion into const_iterator
    It++;
    Map.erase( Obsolete );
    It--;
}

其他回答

... 或者从列表中删除该元素的另一种方法?

这需要-std=c++11标志(用于auto):

auto it=vt.end();
while (it>vt.begin())
{
    it--;
    if (*it == pCursor) //{ delete *it;
        it = vt.erase(it); //}
}

如果你不需要在运行过程中删除所有内容,那么要解决这个问题,你可以使用erase-remove习语:

m_CursorStack.erase(std::remove(m_CursorStack.begin(), m_CursorStack.end(), pCursor), m_CursorStack.end());

remove将容器中与pCursor匹配的所有项交换到最后,并返回指向第一个匹配项的迭代器。然后,使用范围的擦除将从第一个匹配擦除,直到结束。不匹配元素的顺序保持不变。

如果您正在使用std::vector,这可能会更快,其中在内容中间擦除可能涉及大量复制或移动。

当然,上面解释使用reverse_iterator::base()的答案是有趣的,值得了解,为了解决所述的确切问题,我认为std::remove更合适。

虽然在这里使用reverse_iterator的base()方法并对结果进行递减,但值得注意的是,reverse_iterators的状态与常规迭代器不同。一般来说,您应该更喜欢常规迭代器而不是reverse_iterators(以及const_iterators和const_reverse_iterators),原因正是如此。有关原因,请参阅多布斯医生杂志进行深入讨论。

请注意m_CursorStack。如果在for循环中使用erase((++i).base())可能是一个问题(见原始问题),因为它改变了i的值。正确的表达式是m_CursorStack.erase((i+1).base())

下面这段代码将擦除的结果转换回反向迭代器,以便在反向迭代时擦除容器中的元素。有点奇怪,但它即使在擦除第一个或最后一个元素时也能工作:

std::set<int> set{1,2,3,4,5};

for (auto itr = set.rbegin(); itr != set.rend(); )
{    
    if (*itr == 3)
    {
        auto it = set.erase(--itr.base());
        itr = std::reverse_iterator(it);            
    }
    else
        ++itr;
}