我正在尝试这样做:
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需要一个迭代器,而不是反向迭代器。有没有一种方法可以将反向迭代器转换为常规迭代器,或者另一种方法可以从列表中删除该元素?
如果你不需要在运行过程中删除所有内容,那么要解决这个问题,你可以使用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更合适。
有趣的是,这个页面上还没有正确的解决方案。所以,下面是正确的答案:
对于前向迭代器,解决方案是直接的:
std::list< int >::iterator i = myList.begin();
while ( i != myList.end() ) {
if ( *i == to_delete ) {
i = myList.erase( i );
} else {
++i;
}
}
在反向迭代器的情况下,你需要做同样的事情:
std::list< int >::reverse_iterator i = myList.rbegin();
while ( i != myList.rend() ) {
if ( *i == to_delete ) {
i = decltype(i)(myList.erase( std::next(i).base() ));
} else {
++i;
}
}
注:
你可以从一个迭代器构造一个reverse_iterator
你可以使用std::list::erase的返回值
经过更多的研究和测试,我找到了解决方案。显然,根据标准[24.4.1/1],i.base()和i之间的关系是:
&*(reverse_iterator(i)) == &*(i - 1)
(摘自多布斯博士的文章):
因此,在获取base()时需要应用偏移量。因此解决方案是:
m_CursorStack.erase( --(i.base()) );
EDIT
针对c++ 11进行更新。
Reverse_iterator I不变:
m_CursorStack.erase( std::next(i).base() );
Reverse_iterator I是高级的:
std::advance(i, 1);
m_CursorStack.erase( i.base() );
我发现这比之前的解清楚多了。你需要什么就用什么。