0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是迭代器?

汽车电子技术 来源:C语言Plus 作者:Maye426 2023-02-27 15:55 次阅读

一、什么是迭代器?

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

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

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

#include
#include  
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

通过这个例子我们知道了,可以通过迭代器实现算法和容器的分离(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
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,完美~

图片

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Int
    Int
    +关注

    关注

    0

    文章

    23

    浏览量

    16056
  • 数组
    +关注

    关注

    1

    文章

    414

    浏览量

    25905
  • 迭代器
    +关注

    关注

    0

    文章

    43

    浏览量

    4302
收藏 人收藏

    评论

    相关推荐

    使用迭代如何实现指针前移或后移

    显然,迭代是一种更灵活的遍历行为,它可以按任意顺序访问容器中的元素,而且不会暴露容器的内部结构。
    的头像 发表于 09-27 14:06 6247次阅读
    使用<b class='flag-5'>迭代</b><b class='flag-5'>器</b>如何实现指针前移或后移

    谈谈Python 中的迭代模式

    年,Design Patterns - Elements of Reusable Object-Oriented Software)中,它提出了23种设计模式。迭代模式就是其中的一种,在各种编程语言
    发表于 11-23 13:10 776次阅读
    谈谈Python 中的<b class='flag-5'>迭代</b><b class='flag-5'>器</b>模式

    Python高级特性:迭代切片的应用

    在前两篇关于 Python 切片的文章中,我们学习了切片的基础用法、高级用法、使用误区,以及自定义对象如何实现切片用法(相关链接见文末)。本文是切片系列的第三篇,主要内容是迭代切片。 迭代
    发表于 11-29 10:11 655次阅读

    浅谈python中的迭代

      说道python的迭代之前,不得不提到的就是在远古时期的C语言的时代,如果想要对一个数组进行遍历,只能使用for循环。
    发表于 11-24 17:01 305次阅读
    浅谈python中的<b class='flag-5'>迭代</b><b class='flag-5'>器</b>

    请问迭代的实现原理是什么?

    什么是集合框架?LIST接口的实际应用?迭代的实现原理是什么?
    发表于 11-04 09:45

    js迭代异步介绍

    js 迭代 异步 介绍 (Introduction)It’s been a long while coming and I feel it’s high time I made a post
    发表于 09-06 09:26

    python迭代

    python迭代1. 可迭代对象可以利用 for 循环的对象,都叫可迭代对象。列表、元组、字典、字符串等都是可迭代对象。# 以列表为例>>
    发表于 02-24 15:42

    OpenHarmony中的HDF单链表及其迭代

    成员的值设置成第1个节点的地址。因为单链表只支持往一个方向查找,不支持往回查找,如上面的错误范例。如果root记录的是第二个节点地址,则第一个节点变得不可访问。迭代简介迭代是伴随集
    发表于 08-30 10:31

    OpenHarmony中的HDF单链表及其迭代

    节点的地址。因为单链表只支持往一个方向查找,不支持往回查找,如上面的错误范例。如果root记录的是第二个节点地址,则第一个节点变得不可访问。迭代简介迭代是伴随集合概念产生的,意思是
    发表于 09-05 11:38

    算法与数据结构——迭代模式

    第三章为算法与数据结构,本文为3.4 迭代模式。
    的头像 发表于 09-20 17:09 4918次阅读
    算法与数据结构——<b class='flag-5'>迭代</b><b class='flag-5'>器</b>模式

    什么是迭代?我们为什么要使用迭代

    事实上,迭代是一个伴随着迭代模式(Iterator Pattern)而生的抽象概念,其目的是分离并统一不同的数据结构访问其中数据的方式,从而使得各种需要访问数据结构的函数,对于不同
    的头像 发表于 07-21 07:45 1.4w次阅读

    Python学习点:为什么 range() 不生成迭代

    迭代是 23 种设计模式中最常用的一种(之一),在 Python 中随处可见它的身影,我们经常用到它,但是却不一定意识到它的存在。在关于迭代的系列文章中(链接见文末),我至少提到了
    发表于 11-23 13:50 767次阅读
    Python学习点:为什么 range() 不生成<b class='flag-5'>迭代</b><b class='flag-5'>器</b>

    python迭代详解

    python迭代 1. 可迭代对象 可以利用 for 循环的对象,都叫可迭代对象。 列表、元组、字典、字符串等都是可迭代对象。 # 以列表
    的头像 发表于 02-24 15:42 1318次阅读

    简单介绍C++中迭代

    之前的两篇文章我们主要了解了vector和string的相关知识,从中我们知道可以通过下标来访问vector的元素或者string的字符,但是除了这种方式还有一种更为通用的方式获取元素,那就是迭代,这篇文章就会简单介绍迭代
    的头像 发表于 03-17 14:03 488次阅读

    Python中的迭代介绍 迭代在scoreboard中的应用有哪些?

    Iterator Design Pattern: 对容器 (聚合类,集合数据等) 的遍历操作从容器中拆分出来,放到迭代中,实现迭代操作的解耦。
    的头像 发表于 08-08 09:41 578次阅读
    Python中的<b class='flag-5'>迭代</b><b class='flag-5'>器</b>介绍 <b class='flag-5'>迭代</b><b class='flag-5'>器</b>在scoreboard中的应用有哪些?