原创 Maye426 C语言Plus 2020-09-18

一、什么是迭代器?

简单来说,迭代器就是用来遍历容器的。

举个栗子:对于int型数组除了用下标访问,还可以通过指针访问,实际上迭代器就是对指针进行了封装。

通过代码了解一下,自己实现简单的迭代器:

#include<iostream>#include <vector> using namespace std;void show(int* begin, int* end)//自己写的输出函数{  while (begin != end)  {    cout << *begin << " ";    begin++;  }}int main(){  int arr[] = { 1,2,3,4,5,68,5,2,14,5,8,4,5,8,2,5,4,5,65,9 };  int len = sizeof(arr) / sizeof(arr[0]);//求出数组元素个数  //指针访问  int* begin = arr;  int* end = arr + len;  show(begin, end);//在容器中,begin,和end就是迭代器,底层封装了指针
 while (1);  return 0;}


当我们把show函数编程模板函数之后,就可以输出任意类型的数组了:

template<typename _Elem>void show(_Elem* begin, _Elem* end){  while (begin != end)  {    cout << *begin << " ";    begin++;  }}//maindouble da[] = { 2.1,3.14,5.20,6.3,9.5 };len = sizeof(da) / sizeof(da[0]);show(da, da + len);


通过这个例子我们知道了,可以通过迭代器实现算法和容器的分离(show函数可以适配不同类型的数组)。所以说迭代器是一个很强的东西~大家好好学哈

二、迭代器类别

STL 标准库为每一种标准容器定义了一种迭代器类型,这意味着,不同容器的迭代器也不同,其功能强弱也有所不同。

常用的迭代器按功能强弱分为输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器 5 种

输入迭代器:也有叫法称之为“只读迭代器”,它从容器中读取元素,只能一次读入一个元素向前移动,只支持一遍算法,同一个输入迭代器不能两遍遍历一个序列。

输出迭代器:也有叫法称之为“只写迭代器”,它往容器中写入元素,只能一次写入一个元素向前移动,只支持一遍算法,同一个输出迭代器不能两遍遍历一个序列。

正向迭代器:组合输入迭代器和输出迭代器的功能,还可以多次解析一个迭代器指定的位置,可以对一个值进行多次读/写。

双向迭代器:组合正向迭代器的功能,还可以通过++操作符向后移动位置。

随机访问迭代器:组合双向迭代器的功能,还可以向前向后跳过任意个位置,可以直接访问容器中任何位置的元素。

迭代器的操作

操作
所有迭代器it++、++it
输入迭代器*it、it1=it2、it1==it2、it1!=it2
输出迭代器*it、it1=it2
正向迭代器提供输入输出迭代器的所有功能
双向迭代器it--、--it
随机迭代器+=、-=、+、-、[]、<、<=、>、>=


不同容器所支持的迭代器类型表

容器对应迭代器类型
array随机访问迭代器
vector随机访问迭代器
deque随机访问迭代器
list双向迭代器
set / multiset双向迭代器
map / multimap双向迭代器
forward_list前向迭代器
unordered_map / unordered_multimap前向迭代器
unordered_set / unordered_multiset前向迭代器
stack不支持迭代器
queue不支持迭代器
三、基本实现

前面我们说过迭代器实质上就是封装的指针,那么怎么封装的呢?

还是看代码吧~

#include<iostream>using namespace std;
class MyIterator{public:  MyIterator(int* ptr) :_ptr(ptr) {}  int* operator++()//模仿指针前置++操作  {    _ptr++;    return _ptr;  }  int& operator*()//模仿对指针的取值操作  {    return *_ptr;  }  bool operator!=(MyIterator end)//模仿指针的比较  {    return _ptr != end._ptr;  }private:  int* _ptr;};int main(){  int arr[] = { 1,2,3,4,5,68,5,2,14,5,8,4,5,8,2,5,4,5,65,9 };  int len = sizeof(arr) / sizeof(arr[0]);  //模拟迭代器访问  MyIterator begin = arr;  MyIterator end = arr + len;  for (begin; begin != end; ++begin)  {    cout << *begin << " ";  }  while (1);  return 0;}

把指针封装到类里面,这样就可以轻松使用了,不用担心出现乱七八糟的问题。

但是,细心的同学会发现,操作的时候是不用指针了,直接操作迭代器就行,但是赋值的时候还是指针呀~这可咋解决呢?

不要着急,请听我娓娓道来~我们可以把赋值的指针再封装一层,直接返回一个迭代器。不过这里的任务就比较庞大了,

首先,需要把数组用类封装(自己实现简单的vector);

然后,把我们刚刚写好的迭代器类稍加修改,放到类中(迭代器是一个类中类);

最后,直接把数组的首地址,和最后一个元素的下一个位置分别封装成返回迭代器的begin()和end()函数

直接上代码:

template<typename Data>class Vector{public:    Vector() :_Array(nullptr), _curSize(0), _capacity(0) {}    Vector(int size) :_curSize(0), _capacity(size)    {        _Array = new Data[size];    }    void push_back(Data elem)//插入元素{        if (_curSize < _capacity)        {            _Array[_curSize] = elem;            _curSize++;            return;        }    }    Data& operator[](int index)//提供下标法访问元素    {        if (index >= 0 && index < _capacity)        {            return _Array[index];        }        cout << "数组访问越界" << endl;    }    ~Vector()    {        delete[] _Array;    }public://实现迭代器    class iterator    {    public:        iterator() :_ptr(nullptr) {}        iterator(Data* ptr) :_ptr(ptr) {}        iterator(const iterator& it)        {            this->_ptr = it._ptr;        }        ~iterator() {}        iterator operator=(iterator it)        {            this->_ptr = it._ptr;            return *this;        }        bool operator!=(iterator it)        {            return _ptr != it._ptr;        }        iterator operator++(int)        {            iterator temp = *this;            _ptr++;            return temp;        }        Data& operator*()        {            return *_ptr;        }        Data* operator->()        {            return _ptr;        }    private:        Data* _ptr;    };    //提供用于迭代的begin和end函数,这两个函数一定要放在迭代器类的后面    iterator begin()   //返回数组首地址{        iterator t(_Array);        return t;    }    iterator end()//返回数组,最后一个元素的一下一个位置的地址{        iterator t(&_Array[_curSize]);        return t;    }private:    Data* _Array;//数组指针    int _curSize;//数组当前元素大小    int _capacity;//数组最大容量};


代码测试:

void Test(){  Vector<int> vec(10);  for (int i = 0; i < 10; i++)  {    vec.push_back(i);  }  //能通过迭代器访问嘛?不能,要自己实现迭代器之后才能使用  for (Vector<int>::iterator it = vec.begin(); it != vec.end(); it++)  {    cout << *it << " ";  }  cout << endl;}

ok,完美~

STL 迭代器(iterator)用法详解_C语言

你,学废了吗?有任何问题都可在下方留言哦~