STL源码分析-iterator(迭代器)
1. GOF 迭代器设计模式
前面一篇文章有写到stl_list的实现,也实现了一下相应的iterator,但是后面觉得,实现具体容器之前有必要介绍一下iterator(迭代器)
。那么迭代器是什么呢?
GOF的设计模式是这样定义的: 提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
大概意思是,例如一个聚合对象(list),我们该如何来访问它的元素,而又不暴露内部结构;而且还要针对不同的需要,可能以不同的方式遍历这个list;那么即使,我们知道大概会有哪些遍历操作,那我们也不会希望list接口中充斥着各种不同遍历操作。一句话,就是如果把遍历和操作元素的各种方法都放到list中来实现,那么将会导致list类中结构变得混乱而且不稳定。
正好迭代器就是用来提供给外部访问聚合对象元素的一个结构。 那GOF设计模式,采用的实现方式是OOP(面向对象),类图关系如下:

具体的聚合对象有自己的继承关系,具体的iterator也有自己的继承关系,也就是通过继承多态来实现用户侧代码无需修改,就可以兼容不同的聚合对象。在GOF设计模式书中专门有一点提到:使用多态迭代器是有代价的。他们要求用一个Factory Method动态分配迭代器对象。因此仅当必须多态时才使用它们。
2. STL 迭代器
在C++ STL中,也是继承了GOF提出的迭代器基本需求,并且迭代器(iterator)扮演着重要角色,来将将容器和算法分开,彼此独立设计,最后再以胶着剂(iterator)将它们撮合在一起。
那么C++ STL实现iterator和GOF介绍的迭代器实现方法什么区别呢? 那首先我们需要了解C++中的两个编程范式的概念,GP(泛型编程)和OOP(面向对象编程)。
在C++语言里面,我们可以以下方式来简单区分一下GP和OOP:
GP: 泛型编程,也被称为"静态多态",多种数据类型在同一种算法或者结构上皆可操作,其效率与针对某特定数据类型而设计的算法或者结构相同, 具体数据类型在编译期确定,编译器承担更多,代码执行效率高。在STL中利用GP将methods和datas实现了分而治之。
OOP: 将methods和datas关联到一起 (通俗点就是方法和成员变量放到一个类中实现),通过继承的方式,利用虚函数表(virtual)实现运行时类型判定,也叫"动态多态", 由于运行过程中需根据类型去检索虚函数表,因此效率相对较低。
刚好,C++ STL库的整个实现采用的就是GP(Generic Programming),而不是OOP(Object Oriented Programming)。而GOF设计模式采用的
就是继承关系实现的,因此,相对来讲,C++ STL的实现效率会相对较高,而且也更有利于维护。
3. STL iterator分类和总结
迭代器类型基本关系:

STL 迭代器基本介绍:
1、输入迭代器:只读,一次传递
可为输入迭代器预定义实现只有istream_iterator和istreambuf_iterator,用于从一个输入流istream中读取。一个输入迭代器仅能对它所选择的每个元素进行一次解析,它们只能向前移动。一个专门的构造函数定义了超越末尾的值。总是,输入迭代器可以对读操作的结果进行解析(对每个值仅解析一次),然后向前移动。
2、输出迭代器:只写,一次传递
这是对输入迭代器的补充,不过是写操作而不是读操作。为输出迭代器的预定义实现只有ostream_iterator和ostreambuf_iterator,用于向一个输出流ostream写数据,还有一个一般较少使用的raw_storage_iterator。他们只能对每个写出的值进行一次解析,并且只能向前移动。对于输出迭代器来说,没有使用超越末尾的值来结束的概念。总之,输出迭代器可以对写操作的值进行解析(对每一个值仅解析一次),然后向前移动。
3、前向迭代器:多次读/写
前向迭代器包含了输入和输出迭代器两者的功能,加上还可以多次解析一个迭代器指定的位置,因此可以对一个值进行多次读/写。顾名思义,前向迭代器只能向前移动。没有为前向迭代器预定义迭代器。
4、双向迭代器:operator--
双向迭代器具有前向迭代器的全部功能。另外它还可以利用自减操作符operator--向后一次移动一个位置。由list容器中返回的迭代器都是双向的。
5、随机访问迭代器:类似于一个指针
随机访问迭代器具有双向迭代器的所有功能,再加上一个指针所有的功能(一个指针就是一个随机访问迭代器),除了没有一种“空(null)”迭代器和空指针对应。基本上可以这样说,一个随机访问迭代器就像一个指针那样可以进行任何操作,包括使用操作符operator[]进行索引,加某个数值到一个指针就可以向前或者向后移动若干个位置,或者使用比较运算符在迭代器之间进行比较。
可以参考一下之前list实现的iterator代码,iterator内部维护一个list节点指针,然后对++和--进行操作符重载时,其实是指针的前后移动,因此stl_list的迭代器类型为双向迭代器。


迭代器作为STL的一个重要组成部分,今天算是做了一个简单的总结,在后续分析STL其他内容的过程中也会经常遇到!
2018年9月25日23:44:02
STL源码分析-iterator(迭代器)的更多相关文章
- STL源码分析之迭代器
前言 迭代器是将算法和容器两个独立的泛型进行调和的一个接口. 使我们不需要关系中间的转化是怎么样的就都能直接使用迭代器进行数据访问. 而迭代器最重要的就是对operator *和operator-&g ...
- STL源码分析-iterator
http://note.youdao.com/noteshare?id=4efcb6441063dae956c226f91c161897
- STL源码分析《4》----Traits技术
在 STL 源码中,到处可见 Traits 的身影,其实 Traits 不是一种语法,更确切地说是一种技术. STL库中,有一个函数叫做 advance, 用来将某个迭代器(具有指针行为的一种 cla ...
- STL源码分析读书笔记--第二章--空间配置器(allocator)
声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...
- STL源码分析《3》----辅助空间不足时,如何进行归并排序
两个连在一起的序列 [first, middle) 和 [middle, last) 都已经排序, 归并排序最核心的算法就是 将 [first, middle) 和 [middle, last) 在 ...
- STL 源码分析《1》---- list 归并排序的 迭代版本, 神奇的 STL list sort
最近在看 侯捷的 STL源码分析,发现了以下的这个list 排序算法,乍眼看去,实在难以看出它是归并排序. 平常大家写归并排序,通常写的是 递归版本..为了效率的考虑,STL库 给出了如下的 归并排序 ...
- STL 源码分析《2》----nth_element() 使用与源码分析
Select 问题: 在一个无序的数组中 找到第 n 大的元素. 思路 1: 排序,O(NlgN) 思路 2: 利用快排的 RandomizedPartition(), 平均复杂度是 O(N) 思路 ...
- STL源码分析与实现-stl_list容器
1. stl_list 介绍 今天我们来总结一下stl_List, 通过之前介绍单链表的文章,其实对链表的基本操作已经十分熟悉了,那对于stl_list,无非就是链表结构不一样,至于其中的增删改查的细 ...
- STL 源码分析六大组件-allocator
1. allocator 基本介绍 分配器(allocator))是C ++标准库的一个组件, 主要用来处理所有给定容器(vector,list,map等)内存的分配和释放.C ++标准库提供了默认使 ...
随机推荐
- 每天一水poj1502【最短路】
#include<iostream> #include<cstdio> #include<string.h> #include<algorithm> u ...
- 洛谷P3209 [HNOI2010]平面图判定(2-SAT)
传送门 看到哈密顿回路就被吓傻了……结果没有好好考虑性质…… 首先,平面图有个性质:边数小于等于$3n-6$(我也不知道为啥),边数大于这个的直接pass 然后考虑原图,先把哈密顿回路单独摘出来,就是 ...
- python 蓝牙模块pybluz安装
最近项目运用了蓝牙,所以来学一学蓝牙. 经过查阅,知道python的蓝牙模块是pybluz,然后老管理进行安装 出错,提示“Could not find the Windows Platform SD ...
- iOS WKWebView 退出后停止播放音频/视频
带有<video>或者<audio>标签的H5网页在播放音频视频时,退出webview后不会自动停止播放,手动处理一下. 1.注入使网页停止音频.视频播放的JS代码(Swift ...
- zabbix 安装小结
其实很简单的东西,结果折腾了好久.首先去官网 下个source,然后按照文档来 https://www.zabbix.com/documentation/3.2/manual/installation ...
- java 反向工具类
1.ReflectUtil.java package com.example.scansell; import android.util.Log; import java.lang.reflect.C ...
- JS防止页面被其他网站iframe使用方法
if(window.top !== window.self){ window.top.location = window.location;} 这句话的意识是说:如果当前窗体不是顶级窗体,就把自己变成 ...
- P2345 奶牛集会andP2657 低头一族
做法是一样的 题目背景 MooFest, Open 题目描述 约翰的N 头奶牛每年都会参加“哞哞大会”.哞哞大会是奶牛界的盛事.集会上的活动很 多,比如堆干草,跨栅栏,摸牛仔的屁股等等.它们参加活动时 ...
- ES6初探——编译环境搭建
不好意思我又要来写操作文档了,看起来更像wiki的博客(如果你想深入学习,请阅读文末列的参考资料).本文将示例如何把ES6编译成ES5. 首先,你要自行查阅什么是ES6,和ES5.javascript ...
- SecureCRT中vi或vim编辑器显示中文乱码问题
vi ~/.vimrc //新建文件 syntax on set showmode set autowrite set number set encoding=utf-8 fileencodings ...