👦个人主页:@Weraphael
✍🏻作者简介:目前学习C++和算法
✈️专栏:C++航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨
目录
一、什么是迭代器
若要访问容器里的元素,最常见的方式可以通过迭代器。迭代器是一个变量,相当于容器和算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。因此,迭代器可以认为是指针,但不一定就是指针。
特别注意:容器stack
、queue
、priority_queue
是不支持迭代器的
常见的迭代器有正向迭代器和反向迭代器
【正向迭代器】
正向迭代器++
是往后遍历,因此遍历的顺序为1 2 3 4
【代码实现】
cpp
#include <iostream>
#include <vector>
#include <list>
using namespace std;
int main()
{
vector<int> v{ 1, 2,3, 4 };
vector<int>::iterator vit = v.begin();
while (vit != v.end())
{
cout << *vit << ' ';
vit++;
}
cout << endl;
return 0;
}
【输出结果 】
【反向迭代器】
对比正向迭代器,反向迭代器++
是往前遍历的,因此遍历的顺序为4 3 2 1
【代码实现】
cpp
#include <iostream>
#include <vector>
#include <list>
using namespace std;
int main()
{
vector<int> v{ 1, 2,3, 4 };
vector<int>::reverse_iterator vrit = v.rbegin();
while (vrit != v.rend())
{
cout << *vrit << ' ';
vrit++;
}
cout << endl;
return 0;
}
【输出结果】
二、如何模拟实现反向迭代器
我们发现,对比正向迭代器和反向迭代器,只有前后置++/--
是有所差别的。因此,对于list
可以将原来的正向迭代器给拷贝一份,然后将++
运算符重载中修改为指向前一个结点,---
运算符重载修改为指向后一个结点。对于vector
可以是类似于实现list
正向迭代器一样,封装一个类,,然后运算符重载去处理。
可是以上这样实现就有点麻烦,我们可以看看库是如何实现的
从上我们可以发现,在库里面其实使用的是适配器来实现反向迭代器 的,对正向迭代器进行了封装。用正向迭代器的++
实现返向迭代器的++
,用正向迭代器的--
来实现反向迭代器的--
接下来再来看看库里是如何实现reverse_iterator
以上接口唯独最奇怪的是解引用,它解引用的结果是当前位置的前一个对象(*--tmp
),但是再回过头重新看rbegin
和rend
就会明白(上上图)
每次解引用都会先得到rbegin
前一个位置的数据,直到rbegin == rend
遍历结束,这里就体现了一个镜像对称特性,认为反向迭代器与正向迭代器是具有对称关系的
三、代码实现
cpp
#pragma once
namespace wj
{
template<class Iterator, class Ref, class Ptr>
struct ReverseIterator
{
Iterator _it;
typedef ReverseIterator<Iterator, Ref, Ptr> Self;
// 正向迭代器构造反向迭代器
ReverseIterator(Iterator it)
:_it(it)
{}
Ref operator*()
{
// --有副作用,可以拷贝一个副本tmp操作
Iterator tmp = _it;
return *--tmp;
}
Ptr operator->()
{
return &(operator*());
}
Self& operator++() // 前置
{
--_it;
return *this;
}
Self operator++(int) // 后置
{
Iterator tmp(_it);
_it--;
return tmp;
}
Self& operator--()
{
++_it;
return *this;
}
Self& operator--(int)
{
Iterator tmp(_it);
_it++;
return tmp;;
}
bool operator!=(const Self& s) const
{
return _it != s._it;
}
bool operator==(const Self& s) const
{
return _it == s._it;
}
};
}