正向迭代器和反向迭代器之间的关系

正向迭代器和反向迭代器之间的关系

1.1 为何使用迭代器

    谈到迭代器,我们不可避免地会想到STL和泛型编程。在《C++Primer》一书中这样描述到,STL是一种泛型编程(generic programming)。面向对象编程关注的是编程的数据方面,而泛型编程关注的是算法。他们之间的共同点是抽象和创建可重用性代码,但两者的理念绝然不同:泛型编程旨在编写独立于数据类型的代码。这一点最近在学习侯捷老师的《STL源码剖析》一书中深有感触。
    总的来说,模板使得算法独立于存储的数据类型,而迭代器使算法独立于使用的容器类型。因而在vector, set, list中,我们都能见到迭代器的身影。

1.2 迭代器的类型

    STL定义了5种迭代器的类型:输入迭代器,输出迭代器,正向迭代器,双向迭代器和随机访问迭代器。此外,还有一些专用的预定义迭代器类型:reverse_iterator, back_insert_iterator, front_insert_iterator和insert_iterator。

1.3 正向迭代器

    正向迭代器只使用++运算符来遍历容器,所以它每次沿容器向前移动一个元素。正向迭代器可以修改和读取数据。

1.4 反向迭代器

    对于反向迭代器执行递增操作将导致它被递减。最常见的一种使用方式如下:
std::set<int> container;
for (auot iter = container.rbegin(); iter != container.rend(); iter++ )

在这样的场景下,我们可以从容器尾部进行一个遍历。在大数据量且容器内部元素有序的情况下显得尤为有用。

1.5 具体场景

    迭代器在具体的应用场景下可能会和std::find_if()搭配使用,通过条件匹配返回一个置顶元素的迭代器,然后通过erase将其删除。但在反向迭代器中,这种场景将会失效,因为erase并不支持反向迭代器。因而,我们需要一种合理的转换方式。
    关于reverse_iterator的源码:
private:
#ifndef _LIBCPP_ABI_NO_ITERATOR_BASES
    _Iter __t; // no longer used as of LWG #2360, not removed due to ABI break
#endif

#if _LIBCPP_STD_VER > 17
    static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>,
        "reverse_iterator<It> requires It to be a bidirectional iterator.");
#endif // _LIBCPP_STD_VER > 17

protected:
    _Iter current;

我们可以观察到存在一个current的变量,同样也是一个迭代器类型。它的应用场景是什么呢?我们继续观察

reference operator*() const {_Iter __tmp = current; return *--__tmp;}
reverse_iterator& operator++() {--current; return *this;}
reverse_iterator& operator--() {++current; return *this;}

*是解引用的一种方式,我们可以看到,将current赋给了一个临时变量__tmp, 然后该变量先执行自减操作,再取出存储的值。前面我们提到,反向迭代器其实是从后往前,从rbegin到rend,在直观上是一种"+“, 实际上,从正向的角度来看,其实是”-", 这这好对应代码块的下两行,也就是说current和正向迭代器是存在关联的。

rbegin指向容器的最后一个元素,存在超尾现象,因此,在取最后一个元素时,首先需要将目前指向位置自减,然后再解引用。其余元素依次类推。
因而将反向转为正向时,我们可以调用base()函数,得到current。但实际上current目前实际指向是目标元素的后一位,再去解引用并不是预期行为。所以我们需要首先对反向迭代器执行一个自增,current会自减,进而指向目标元素,通过base()返回正确的迭代器。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值