boost的文档specialized iterator adaptors指出boost::reverse_iterator
“纠正了C++ 98的std :: reverse_iterator的很多缺点。”std :: reverse_iterator有什么缺点?
这些缺点是什么?我似乎无法找到这些缺点的描述。
后续问题:
如何提高:: reverse_iterator的纠正这些缺点?
boost的文档specialized iterator adaptors指出boost::reverse_iterator
“纠正了C++ 98的std :: reverse_iterator的很多缺点。”std :: reverse_iterator有什么缺点?
这些缺点是什么?我似乎无法找到这些缺点的描述。
后续问题:
如何提高:: reverse_iterator的纠正这些缺点?
嗯,最大的问题是他们不是转发迭代器,而且有些东西几乎期望了前向迭代器。所以,你必须做一些有趣的转换才能使事情发挥作用。要列举一些问题
的erase()
某些版本和insert()
需要迭代器,而不是反向迭代器。这意味着如果您使用的是反向迭代器,并且您想要insert()
或erase()
,那么您将不得不使用反向迭代器的base()
函数来实现前向迭代器。没有自动转换。
base()
根据插入返回等价于反向迭代器的前向迭代器。也就是说,将插入插入到当前元素的前面。因此,如果base()
为您指定了指向相同元素的迭代器,则反向迭代器指向的元素将是指向的错误元素。所以,它指向前进一步,你可以使用它来插入。
因为base()
返回一个指向不同元素的迭代器,所以它是erase()
的错误元素。如果您在base()
的迭代器上调用erase()
,则会从容器中删除反向迭代器指向的元素中的一个元素,因此您必须在调用base()
之前递增反向迭代器,以便获得正确的前向迭代器用于erase()
。
是否可以使用base()
与erase()
正确擦除元素完全取决于您的实现。它适用于gcc,但对于Visual Studio,它们实际上只是包装一个前向迭代器,以便在处理逆向迭代器和Visual Studio时无法使用erase()
。我不记得insert()
是否有同样的问题,但是反向迭代器在C++的不同实现之间工作不一样(根据Visual Studio人员,标准不够清楚),所以它可能有点毛将它们用于除了遍历容器之外的其他任何东西。
可能有其他一些问题,但处理的不是非常量,前向迭代用C++做的比简单地在一个容器的遍历其它任何时候能有点毛茸茸的其他任何类型的迭代器 - 如果你甚至可以做到这一切 - 因为这么多的函数需要非常量前向迭代器而不是任何其他类型的迭代器。
如果你真的想知道各种迭代类型和与它们相关的问题之间的差异,我推荐阅读Scott Meyer的Effective STL。它对迭代器有很大的帮助。
编辑:至于如何Boost的逆迭代纠正这些缺点,恐怕我没有线索。我意识到一些标准的反向迭代器的缺点,并且在过去被它们咬了,但是我从来没有用过Boost,所以我对它们的反向迭代器根本不熟悉。抱歉。
我不确定我看到你在看什么。 “预计”前向迭代器的代码不应该“注意到”任何区别,除非它们执行未定义的行为...... – Cogwheel 2010-07-08 20:31:39
C++ 03中的std :: reverse_iterator模板公开了与基础迭代器相同的迭代器类别必须至少是一个双向迭代器,所以reverse_iterator总是至少是一个双向迭代器(因此也是一个前向迭代器)。 – 2010-07-08 20:35:30
我不相信你在这里是正确的。我认为reverse_iterator实际上是一个前向迭代器。至少我不知道它违反了这个概念。 – 2010-07-08 20:35:49
它往往有点.....早产。 – 2010-07-08 20:27:33
作为评论发布,因为我只是猜测:'std :: reverse_iterator <>'的早期实现有时会有错误。 Boost可能只是试图隔离这种情况。也许这个评论更多的是关于'reverse_iterator'实现中的缺点,而不是标准中的缺点? – 2010-07-08 20:52:41