如何用反向迭代器调用擦除

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

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

但是,擦除需要一个迭代器,而不是一个反向迭代器。 有没有办法将逆向迭代器转换为常规迭代器,或者有其他的方法来从列表中删除这个元素?

经过一些更多的研究和testing,我find了解决scheme。 显然根据标准[24.4.1 / 1],i.base()和i之间的关系是:

 &*(reverse_iterator(i)) == &*(i - 1) 

(来自Dr. Dobbs的文章 ):

替代文字

所以你需要在获得base()时应用一个偏移量。 因此解决scheme是:

 m_CursorStack.erase( --(i.base()) ); 

编辑

更新C ++ 11。

reverse_iterator i是不变的:

 m_CursorStack.erase( std::next(i).base() ); 

reverse_iterator i是高级的:

 std::advance(i, 1); m_CursorStack.erase( i.base() ); 

我觉得这比我以前的解决scheme更清晰。 使用您需要的任何一个。

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

…或者从列表中删除这个元素的另一种方法?

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

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

在使用reverse_iteratorbase()方法并在此处递减结果时,值得注意的是, reverse_iterator不具有与常规iterator相同的状态。 一般来说,您应该更喜欢使用常规iteratorconst_reverse_iterator s(以及const_iteratorconst_reverse_iterator ),这是因为这样的原因。 看Dobbs医生的杂志深入讨论为什么。

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

如果你不需要清除所有的东西,那么为了解决这个问题,你可以使用erase-remove idiom:

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

std::remove将容器中与pCursor匹配的所有项目pCursor到最后,并将迭代器返回到第一个匹配项目。 然后,使用范围的擦除将从第一次擦除擦除,并结束。 保留不匹配元素的顺序。

如果你使用的是std::vector ,那么在内容中删除可能涉及大量的复制或移动,这可能会更快。

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

只是想澄清一些事情:在上面的一些评论和回答中,擦除的可移植版本被提及为(++ i).base()。 但是,除非我错过了正确的语句是(++ ri).base(),这意味着你“增加”了reverse_iterator(而不是迭代器)。

我遇到了需要做类似的事情昨天,这个post是有帮助的。 感谢大家。