SGISTL源码探究-迭代器的类型

从零开始:TexLive(Latex)安装与配置全指南 本文提供了一份详尽的TexLive(Latex)安装与配置全指南,旨在帮助用户从零开始快速搭建LaTeX工作环境。内容涵盖从镜像下载、安装步骤详解、环境验证到高效编辑器(如VS Code)配置,并特别强调了中文排版支持与宏包管理,确保用户能顺利处理学术论文等专业文档的排版需求。 阅读详情

前言

迭代器主要用于将数据结构与算法粘合在一起。当我们平时使用迭代器的时候,主要的操作无非是使用operator *以及operator ->,之所以它表现的像指针,就是因为对这两个操作符进行了重载。而不同的容器因为其存储的数据结构不同,比如访问其成员时,若是单链表,则不支持向前遍历,因此缺少跟其他迭代器的一些功能;而一些算法也会根据数据结构能否支持某种操作(比如随机访问)来选择最有效率的做法。

迭代器的五种类型

根据这些原因,每个容器都有自己的迭代器来满足自己的使用并且将迭代器分为五类。
分别是:

  • Input Iterator : 该类型迭代器指向的对象只读(基类)
  • Output Iterator : 该类型迭代器指向的对象只写(基类)
  • ForWard Iterator : 可读可写,但是同样只支持简单的向前操作,不能后退(多重继承自前两个类)
  • Bidirectional Iterator : 在Forward Iterator的基础上,支持了前后移动(单继承自Forward Iterator)
  • Random Access Iterator : 这种类型最为自由,可以随机访问/修改元素,支持指针的所有算术操作。(单继承自Bidirectional Iterator)

将这五种类型设置为类的其中一个好处就是一个Random Access Iterator类型的迭代器同样也可以用于支持Bidirectional Iterator的算法。

我们可以先来看看根据迭代器类型的不同区分的不同的情况的例子:

distance

该函数用于计算传入的first和last迭代器之间的距离

//如果迭代器类型是Random以下的,都调用这个__distance
//采用循环遍历的方式来计算first到last的距离
template <class InputIterator, class Distance>
inline void __distance(InputIterator first, InputIterator last, Distance& n, input_iterator_tag) {
  while(first != last) { ++first; ++n;}
}
//如果迭代器是RandomAccessIterator,则调用效率最佳的__distance
//直接用last-first
template <class RandomAccessIterator, class Distance>
inline void __distance(RandomAccessIterator first, RandomAccessIterator last, Distance& n, random_access_iterator_tag) {
  n += last - first;
}
//根据迭代器的类型不同,调用不同的__distance
template <class
 InputIterator, class Distance>
inline void distance(InputIterator first, InputIterator last, Distance& n) {
  __distance(first, last, n, iterator_category(first));
}

再看到distance函数,它根据iterator_category(first)的返回值不同而调用不同的__distance。看起来似乎iterator_category可以判断当前迭代器的类型。

iterator_category到底是什么,等下我们再来分析。

深入源码

知道了迭代器的五种类型,下面我们直接来看它的源码是如何实现的(没什么比看源码来的直接)

/* 首先这五种类型的继承关系一目了然
 * 其中没有任何成员,全是空类
 * 这样做可以很方便的利用类之间的转换来达到类型转换的效果
 */
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
/* 可以看到它们都统一了:
 * iterator_category
 * value_type
 * difference_type
 * pointer
 * reference
 * 这5个统一的迭代器相应型别
 */
template <class T, class Distance> struct input_iterator {
  typedef input_iterator_tag iterator_category;
  typedef T                  value_type;
  typedef Distance           difference_type;
  typedef T*                 pointer;
  typedef T&                 reference;
};

struct output_iterator {
  typedef output_iterator_tag iterator_category;
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;
};

template <class T, class Distance> struct forward_iterator {
  typedef forward_iterator_tag iterator_category;
  typedef T                    value_type;
  typedef Distance             difference_type;
  typedef T*                   pointer;
  typedef T&                   reference;
};


template <class T, class Distance> struct bidirectional_iterator {
  typedef bidirectional_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef Distance                   difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

template <class T, class Distance> struct random_access_iterator {
  typedef random_access_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef Distance                   difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

可以看到除了Output Iterator比较特殊,其余的迭代器类型都将iterator_category定义为各自的类型,而其他的都一致。
这里简单的说明一下迭代器类型中的这五个不同的迭代器相应型别代表什么含义:

  • iterator_category:用于获取到迭代器的类型,对应上面的例子中的iterator_category()可以判断出传入的迭代器的类型
  • value_type:代表迭代器指向对象的数据类型
  • difference_type:代表两个迭代器之间的距离
  • pointer:代表对象T的指针
  • reference:顾名思义,即代表对象T的引用

除了认识到迭代器的不同类型的对象有什么不同之外,还可能会对它们统一都提供的这五种相应型别产生疑惑,我们将在后面进行具体的分析。

小结

在本小节中我们了解了迭代器的五种类型,并引出了迭代器的五种相应型别,但是在正式分析这五种相应型别之前,我们需要先对traits编程技法有个了解。

20 硬件工程师笔面试高频考点真题解析——寄存器 摘要: 寄存器是由多个边沿触发的D触发器组成的多位存储单元,用于同步时序电路中的数据暂存、隔离毛刺、跨时钟域同步等。选型需考虑位宽、触发方式(边沿/电平)、异步控制、电气参数等。核心时序参数包括建立时间(Tsu)、保持时间(Thold)和时钟输出延迟(Tco)。寄存器广泛应用于时序逻辑、流水线分割、毛刺消除、跨时钟域同步及计数分频等场景。同步复位依赖时钟边沿,时序易收敛但需时钟支持;异步复位独立于时钟,上电可靠但需注意亚稳态风险。 阅读详情

相关推荐

告别上位机!用MCGS触摸屏+FTP服务器,5分钟搞定工控机文件自动同步

本文介绍了一种工业自动化领域的高效解决方案,通过MCGS触摸屏结合FTP服务器实现工控机文件的自动同步,无需开发上位机软件。该方案特别适用于图像采集、参数同步、数据备份等场景,具有成本低、可靠性高、维护简便等优势。详细配置指南和实战案例帮助用户快速实现零代码文件同步。

weixin_30872499的博客 560

C++学习26:迭代器深度探索之iterator_category、IO流适配器

迭代器我们在前面已经学习过: 1.迭代器的4个操作符重载,即移动和取值的方式; 2.迭代器的5个typedef,即iterator_traits; 下面我们将进行iterator_category的学习 1 简介 1.1 种类 一共有5种iterator_category分别为: 1、input_iterator:istream独有的迭代器。 2、output_iterator:ostream独有...

时间有泪 2381

Linux运维踩坑实录:手把手教你修复LVM中PV显示[unknown]的诡异问题

本文详细解析了Linux运维中LVM物理卷(PV)显示[unknown]的故障现象及修复方法。通过分析问题根源、提供标准修复流程和特殊场景处理方案,帮助运维人员快速解决VG容量异常、PV状态丢失等问题,并分享预防措施与最佳实践,确保LVM存储系统的稳定运行。

weixin_26869081的博客 348

C++STL详解三:迭代器

迭代器的简单实现以及标准对STL的要求

qq_34269632的博客 862

Linux安装部署PostgreSQL详细步骤

Linux安装部署PostgreSQL详细步骤

2301_77356579的博客 9321

Qt Tab Widget 实战:如何打造一个可动态增删的标签页管理器(附完整代码)

本文深入探讨了使用Qt框架中的Tab Widget控件构建动态标签页管理器的实战方法。通过分析动态增删的核心挑战,提供了完整的C++代码示例,涵盖信号槽机制、页面生命周期管理、上下文菜单实现以及状态持久化等关键功能,帮助开发者打造高效、用户友好的桌面应用界面。

bb456的博客 1043

C++五种类型的迭代器

迭代器定义了常用的操作集,但有些迭代器具有比其他迭代器更强大的功能。例如ostream_iterator只支持自曾、解引用和复制运算,而vector容器提供的迭代器除了这些运算,还支持自减、关系和算数运算。因此,迭代器可根据所提供的操作集进行分类。类似地,还可根据算法要求它的迭代器提供什么类型的操作,对算法分类。有一些算法,例如 find,只要求迭代器提供读取所指向内容和自增的功能。另一些算法,,

ZoMoe's eye 8994

如何在SpringBoot中实现AI 流式输出?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 1479

SGI STL 学习笔记一 Iterator

  之前一直希望能够看STL源代码,因为他一直存放在我的硬盘深处。但是由于复杂性,我一直再绕。而且纠结的是,我一直推荐我的学弟去研读STL。由于最近的工作需要,使我不得不一看STL的究竟。当然,STL对我来说依然是太庞大了,有相当多的相关的基础知识的缺乏导致整个过程实在是太艰难了,直到我看到了《SGI STL 源码剖析》。之后我的很多例子其实就是这本书的源代码。真的,这又是一本经典的著作。这本书贯...

weixin_30588907的博客 150

Python爬虫实战:全网政府招标信息采集与整合

本文详细介绍了如何使用Python构建一个完整的政府招标信息爬虫系统,涵盖了从数据采集、解析、存储到质量监控的全流程。多源采集:支持多个地方政府网站的同时采集智能解析:自动适应不同网站结构,智能提取关键信息异步高效:使用异步编程提高采集效率反爬应对:内置多种反爬虫应对策略数据质量:完善的数据清洗和质量监控机制易于扩展:模块化设计,便于添加新的数据源。

2201_76125261的博客 1380

[DDR5]DDR5 SDRAM 状态图 和 基本功能

DDR5 SDRAM的读写操作以突发(burst mode)为导向,从选定的位置开始,并按照编程顺序进行16个突发长度或8个“切片”突发长度的操作。从ACTIVATE命令开始,然后是读取或写入命令。

串起点滴 1200

【迭代器】迭代器相应型别

迭代器相应类型有五种,`iterator_traits`类专门用来“萃取”迭代器的特性。

li1358159的博客 1575

android 14.0 控制wifi启用禁用功能实现

在14.0的产品rom定制化开发中,在产品开发中,对于功能的开发的功能也是挺多的,而在对于wifi的功能定制需求,有要求需要通过系统属性来控制wifi开关是否可以打开 来控制是否可以连接wifi,打开控制wifi的功能,接下来分析wifi的开启流程来实现该功能的实现

安卓兼职framework和app工程师的博客 1771

SGISTL源码探究-vector容器(上)

前言vector容器应该算是最常用的容器之一了,它是序列式容器的一种,即元素可被排序。vector被称为动态数组,可以随着元素的加入,内部的大小自行扩充。可能你对vector的机制有所耳闻,比如每次扩充时,扩充当前容量的2倍等。接下来,我们就进入到它的源码来看看vector是如何实现的。我们将它分为四部分进行分析,vector的迭代器,vector的内存分配及构造,vector的内存控制以及一些常用

Move_now的博客 810

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

SGISTL源码探究-STL中的红黑树(上)

前言本小节将进入到SGISTL的红黑树部分。关于红黑树,是一种比较复杂的数据结构,但是并不是特别难。如果对红黑树不太了解,可以去网上查阅相关的资料,因为本文的主要目的是分析STL中的红黑树的源码,和普通的红黑树略有不同,还要复杂一些,需要有一定的基础。基本概念首先什么是二叉搜索树,二叉搜索树即符合任何一个节点的值一定大于其左子树的任何一个节点的值并且小于其右子树的任何一个节点的值(节点的值不允许重复

Move_now的博客 1806

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

SGISTL源码阅读五 迭代器上(迭代器的五种相应型别associated types)

SGISTL源码阅读五 迭代器上(迭代器的五种相应型别associated types) 前言 之前在对STL的简介中说到过,迭代器的作用是将数据结构(容器)和算法粘合在一起,我们可以将它理解成smart pointer,它是一种行为类似指针的对象。 什么是相应型别? 最初看到这个翻译觉得这个概念特别高大上,但是我们不要把它想得太复杂。 大家应该比较熟悉sizeof()吧,我们可以调用它来获取变量...

Lyn&Xx 570

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

SGISTL源码-迭代器 笔记

阅读SGISTL源码迭代器部分的笔记

weixin_46065476的博客 466

SGISTL源码探究-STL中的hashtable(上)

前言关于哈希表部分,哈希函数以及解决哈希冲突的方法都有很多种,在本文中不会详细去讨论哈希表的大量知识,而是以SGISTL实现的hashtable为主,所以如果对hashtable不太了解,建议先去网上查阅相关的资料。这里只给出基本的概念。了解哈希表原理基本概念哈希表(hashtable,也称散列表):根据key来访问元素的一种数据结构。它可能先经过哈希函数计算出key,然后通过key访问表中对应ke

Move_now的博客 1483

SGISTL源码阅读六 迭代器下(iterator_traits)

SGISTL源码阅读六 迭代器中(traits编程技法) ####前言 上一篇博客我们了解了迭代器的相应型别,简单的参数推导机制可以实现针对不同的类型进行不同的操作,但是这并不能解决所有的情况。本文章将要介绍_STL源代码门钥_——traits编程技法。 凡是原生指针,都没有能力定义自己的相应型别,它们不是一种class type,traits编程技法利用模板偏特化解决了这个问题。 声明内嵌型别 ...

Lyn&Xx 265

迭代器const_iterator和iterator的实现方法与迭代器比较运算符的优化

最近在跟着侯捷老师的《STL源码剖析》学习SGI STL的源码,发现const_iterator和iterator的实现细节实在巧妙,想写一篇文章跟大家分享一下。

weixin_51829359的博客 1749

SGISTL源码探究-deque容器(上)

前言deque容器比list以及vector容器都要复杂的多。它用两端都有开口的线性空间来存储数据,这样的话在首部操作数据的效率比vector高,以及虽然它的迭代器是random_access_iterator_tag型的,但是并不是原生指针,需要封装,比list和vector的迭代器都要复杂。它实现的机制是利用二级指针,维护一个指针数组map,然后数组中存储的指针指向具体的线性空间。 map并不

Move_now的博客 786

SGISTL源码阅读二十三 hashtable下

SGISTL源码阅读二十三 hashtable下 前言 之前介绍了hashtable的基本结构和它的构造方法,现在我们继续来学习它的迭代器和一些常用方法。 深入源码 hashtable的迭代器 //迭代器的声明 template &amp;amp;lt;class Value, class Key, class HashFcn, class ExtractKey, class EqualKe...

Lyn&Xx 274

SGISTL源码探究-stl_algo.h中的基础算法

前言在上一小节中我们分析了stl_algobase.h中的算法,虽然都是一些比较基础的算法,但是了解其中的泛化以及特化的思想是很重要的。在本小节中我们将分析stl_algo.h中的算法,里面的大部分算法也很基础,比较复杂的我们放在另外的小节分析。各算法的实现for_each遍历[first, last),每个元素使用仿函数f进行处理。注意传入的迭代器类型是InputIterator,所以可能不支持赋

Move_now的博客 803

SGISTL源码探究-stl_algobase.h中的算法

前言在上一小节中,我们分析了stl_numeric.h中的算法部分。在本小节中,我们将分析stl_algobase.h文件中的算法,里面实现的都是一些比较基本的算法,比如equal、fill、max、swap等,可以从中学习到泛型的思想。stl_algobase.h中的算法iter_swap该函数的作用是交换迭代器指向的两个元素。注意迭代器的类型必须是ForwardIterator及其派生类。 并

Move_now的博客 1244

SGISTL源码探究-stl_numeric.h中的数值算法

前言上一小节中,我们对stl中的算法部分做了一个大致的说明。本小节我们将进入到其中关于数值算法的部分,都在stl_numeric.h文件中。废话不多说,直接看源码吧。stl_numericaccumulate注意该算法要求了迭代器的类型至少是InputIterator类型,如果是OutputIterator类型,肯定是不行的。 用于计算元素总和,init加上[first, last)范围内的元素之

Move_now的博客 682

SGISTL源码阅读十四 deque容器上

SGISTL源码阅读十四 deque容器上 deque概述 之前我们学习过vector,我们知道他的扩容方式是从尾部扩容,也就是它是单向开口的。deque比vector和list都要更复杂一些,它是双向开口的,也就是说可以在头部和尾部做同样的操作(我们要向vector的头部添加一个元素代价是相当大的,需要将所有元素向后移动,但是对于deque来说,在头部和尾部操作都是同样的时间复杂度)。这样看起来...

Lyn&Xx 278
上一篇: SGISTL源码探究-默认使用的配置器
下一篇: SGISTL源码探究-traits技法
UKey_
博客等级 码龄10年 258粉丝 186原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值