比较 vector<T>::iterator 和 vector<T>::reverse_iterator。

28

我正在做一个练习,其中我有一个向量,并且我正在编写自己的反转算法,通过使用反向迭代器和正向迭代器来反转向量的内容。但是,我无法比较这些迭代器。

int vals[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
vector<int> numbers(vals, vals + 10);

vector<int>::iterator       start = numbers.begin();
vector<int>::reverse_iterator end = numbers.rend();

我之前有一个通过使用两个迭代器来反转向量的算法,但是在这个任务中,我不能使用 != 运算符来比较它们。我的猜测是要获取向量中彼此的基础指针或索引,但是如何获取这些指针/索引呢?


针对您的练习,使用两个前向迭代器就会更容易:for (vector<int>::iterator i = numbers.begin(), j = numbers.end(); i < j; ++i) { --j; std::iter_swap(i,j); } - Steve Jessop
5个回答

22
使用 base() 返回的迭代器进行比较:it == rit.base() - 1

3
不过需要注意,如果rit是一个末尾迭代器(即反向迭代的结尾),那么rit.base()就是numbers.begin(),从中减去1就会产生未定义行为。另一种方法是比较distance(numbers.begin(), it) == distance(rit, numbers.rend()) - 1 - Steve Jessop
1
@SteveJessop: 当然,还有一个问题,就是“-1”不能应用于BidirectionalIterators,只能应用于RandomAccessIterators,因此@wilx提供的代码对于“list”无效。 - Matthieu M.
建议通过 it==std::prev(rit.base()) 移除随机访问要求。 - exa
1
@exa:这是针对涉及向量迭代器的特定问题的答案。虽然通常按照您的方式进行操作可能是个好主意,但在这种情况下并不必要。我相信大多数人都能自己推广这个概念。 - wilx

10
您可以通过调用base()reverse_iterator转换为iterator

但是,请注意,有一些注意事项。@Matthieu M.的评论特别有帮助:

注意:base()实际上返回一个指向reverse_iterator指向的元素之后的iterator


7
请注意:base()实际上返回指向reverse_iterator所指元素之后的一个元素的迭代器。 - Matthieu M.
@Matthieu M.:是的,这就是我要写的主要注意事项 - 但既然你已经写了,我想我不必再写了。谢谢! - Reunanen
@TobySpeight:你说得对,所以我现在就做了这件事。 - Reunanen

3

2

这两种类型不能进行比较(这是一个非常好的想法),在我看来调用.base()并不是很优雅(或通用)。 您可以转换类型并比较结果。 考虑到涉及reverse_iterators的偏移量规则。

iteratorreverse_iterator的转换需要显式指定(幸运的是),但是从reverse_iterator到iterator的转换是不可能的(不幸的是)。 因此,只有一种方法可以进行转换,然后进行比较。

    std::vector<double> vv = {1.,2.,3.};
    auto it = vv.begin();
    auto rit = vv.rend();
//  assert( it == rit ); // error: does not compile
    assert(std::vector<double>::reverse_iterator{it} == rit);

1
你可以使用 (&*start == &*(end - 1)) 直接比较迭代器所指向的地址。

6
你可以这样做,但你应该这样做吗? :) - BartoszKP
这并没有回答问题。OP问的是如何比较迭代器和反向迭代器,而不是如何比较起始元素和end-1元素的地址。 - RichS

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