STL 源码分析 # stl_iterator & stl_iterator_base #

STL 源码分析 # stl_iterator_base && stl_iterator #

这里能很清楚的看到各个基础类型的继承关系

template <class _Tp, class _Distance> struct input_iterator {
  typedef input_iterator_tag iterator_category;
  typedef _Tp                value_type;
  typedef _Distance          difference_type;
  typedef _Tp*               pointer;
  typedef _Tp&               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 _Tp, class _Distance> struct forward_iterator {
  typedef forward_iterator_tag iterator_category;
  typedef _Tp                  value_type;
  typedef _Distance            difference_type;
  typedef _Tp*                 pointer;
  typedef _Tp&                 reference;
};

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

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

五个类的实现中都有

  • iterator_category    集中迭代器策略.
  • value_type             所谓的value_type是指迭代器所知对象的型别.任何一个打算与STL完美搭配的class 都应                               该定义自己的value_type
  • difference_type  用来表示两个迭代器之间的距离,因此他也可以用来表示一个容器的最大容量.因为对于连续                              空间的容器而言,头尾之间的距离就是其最大容量.如果一个泛型算法提供计数功能,例如                                  STL的count(),其返回值就必须是迭代器difference type
  • pointer                   指针啦..
  • reference              在C++中, 函数如果要传回左值, 都是以by reference的方式进行, 所以当p是一个mutable iterators时, 如果其value_type是T, 那么*p的型别不应该是T, 而应该是T&.

五个成员.

对于迭代器的策略,又有五种:

input iterator: 这种迭代器所知的对象不允许外界改变. read only

output iterator: write only

forward iterator: 允许写入型算法在此迭代器所形成的区间上进行读写操作.

bidirectional iterator: 可双向移动的迭代器.

random access iterator: 前面四种迭代器都只供应一部分指针运算能力(前三种只支持++, 第四种开始支持--,). 这里第五种random access iterator支持所有指针算术能力. p +n, p -n, p[n], p1- p2, p1 < p2

这里你能看到__advance 函数被各种重载. 五种迭代器里面, 四种都有相应的版本, 但是就是没有对于forward iterator的版本,

关于back_insert_iterator迭代器的实现: 在我看来,其实就是对于一个container指针的封装.

这个指针实质上指向对应的class 类型(_Container). 而对这个迭代器赋值, 实质上就是把value 通过调用push_back()函数置于最后.

back_inserter函数的实现:

类似的, 有前向插入迭代器 front_insert_iterator

front_inserter()函数的实现.

后面迭代器类似这种构造方式的不再赘述.

比较两个迭代器相等实质上还是比较迭代器类所维护的指针是否相等.

下面的迭代器会调用base()返回他们维护的指向对象的指针.

你会发现前面的各种insert迭代器都是维护的一个指针, 但是到了各种reverse iterator的时候好像就是维护的一个具体的对象了.看下面:

这就是细节. 其实这里各种reverse iterator本质上还是维护的指针, 为什么呢? 他们间接的维护一个前向的迭代器,只是改变这个前向迭代器的运算方式而已!!

所以, 他这里表现出的具体的维护的是一个迭代器了, 而不是指针!

下面看看 IO 流迭代器istream_iterator 和ostream_iterator

下面几乎就是一个istream_iterator的全貌.

这个类最核心的任务也就是维护他那三个私有成员

_M_stream

_M_value

_M_ok

默认的构造函数会把_M_stream(一个指针)初始化为0, 而bool值 _M_ok为false

_M_read()当 _M_stream指针非空的时候才可以从 _M_stream指向的地址处读取一个值, 并把值存放在 _M_value.

下面是输出迭代器 ostream_iterator的实现.

整个类就是为了维护好 _M_stream 和 _M_string两个私有成员,

就这些, 其他细节不再赘述, RTFSC : )

时间: 2024-10-05 23:07:20

STL 源码分析 # stl_iterator & stl_iterator_base #的相关文章

stl源码分析之vector

上篇简单介绍了gcc4.8提供的几种allocator的实现方法和作用,这是所有stl组件的基础,容器必须通过allocator申请分配内存和释放内存,至于底层是直接分配释放内存还是使用内存池等方法就不是组件需要考虑的事情.这篇文章开始分析gcc4.8 stl的容器源码实现.stl的容器分为序列式容器和关联式容器,前者包括vector,list,queue以及stack等常用数据结构,后者包含了map,set以及hash table等比较高级的结构,本文就从使用最广泛也是最基础的vector开始

stl源码分析之hash table

本文主要分析g++ stl中哈希表的实现方法.stl中,除了以红黑树为底层存储结构的map和set,还有用哈希表实现的hash_map和hash_set.map和set的查询时间是对数级的,而hash_map和hash_set更快,可以达到常数级,不过哈希表需要更多内存空间,属于以空间换时间的用法,而且选择一个好的哈希函数也不那么容易. 一. 哈希表基本概念 哈希表,又名散列表,是根据关键字直接访问内存的数据结构.通过哈希函数,将键值映射转换成数组中的位置,就可以在O(1)的时间内访问到数据.举

stl源码分析之list

本文主要分析gcc4.8版本的stl list的源码实现,与vector的线性空间结构不同,list的节点是任意分散的,节点之间通过指针连接,好处是在任何位置插入删除元素都只需要常数时间,缺点是不能随机访问,查询复杂度是O(n),n为list中的元素个数.所以list非常适合应用与数据插入删除频繁的场景. 一. list节点 list节点定义如下, struct _List_node_base { _List_node_base* _M_next; _List_node_base* _M_pre

STL源码分析--仿函数 &amp; 配接器

STL源码分析-仿函数 & 配接器 仿函数就是函数对象.就实现观点而言,仿函数其实就是一个"行为类似函数"的对象.为了能够"行为类似函数",其类别定义中必须自定义(或说改写.重载)function call 运算子(operator()),拥有这样的运算子后,我们就可以在仿函数的对象后面加上一对小括号,以此调用仿函数所定义的operator().仿函数作为可配接的关键因素. 配接器在STL组件的灵活组合运用功能上,扮演着轴承.转换器的角色,adapter的定

stl源码分析之priority queue

前面两篇介绍了gcc4.8的vector和list的源码实现,这是stl最常用了两种序列式容器.除了容器之外,stl还提供了一种借助容器实现特殊操作的组件,谓之适配器,比如stack,queue,priority queue等,本文就介绍gcc4.8的priority queue的源码实现. 顾名思义,priority queue是带有优先级的队列,所以元素必须提供<操作符,与vector和list不同,priority queue允许加入元素,但是取出时只能取出优先级最高的元素. 一. pri

STL源码分析--空间配置器的底层实现 (二)

STL源码分析-空间配置器 空间配置器中门道 在STL中的容器里都是使用统一的空间配置器,空间配置器就是管理分配内存和销毁内存的.在STL将在heap空间创建一个对象分为两个步骤,第一是申请一块内存,第二是在这块内存中初始化一个对象.首先申请空间是由malloc提供,初始化一个对象时由constructor管理.销毁一个对象也是由两步骤完成,第一是销毁空间上的对象,第二是释放这块内存. 同时,STL的空间配置器分为两级内存,如果申请的内存空间大于128KB,那么就使用第一级空间配置,如果小于,那

STL源码分析--仿函数 &amp; 模板的模板参数 &amp; 临时对象

STL源码分析-使用的一些特殊语法 关于泛型编程中用到的一些特殊语法,这些语法也适用于平常的模板编程 1.  类模板中使用静态成员变量 Static成员变量在类模板中并不是很特殊,同时这个变量不属于对象,属于实例化以后的这个类类型.每一个实例化对应一个static变量 2.  类模板中可以再有模板成员 3.  模板参数可以根据前一个模板参数而设定默认值 4.  类模板可以拥有非类型的模板参数 所谓非类型的模板参数就是内建型的模板参数 Template <class T,class Alloc =

STL源码分析--萃取编程(traits)技术的实现

1.为什么要出现? 按照默认认定,一个模板给出了一个单一的定义,可以用于用户可以想到的任何模板参数!但是对于写模板的人而言,这种方式并不灵活,特别是遇到模板参数为指针时,若想实现与类型的参量不一样的实例化,就变得不太可能了!也有时,想禁止此种相同的实例化变得不太可能!故而出现了,Partial Specialization! 同时,在使用void*指针时,可以最大限度的共享代码,减少代码的膨胀! 2.它是什么?其实,就是用户定义的偏特化.用template<>来说明这是一个偏特化,针对任何模板

STL源码分析--算法

STL源码剖析-算法 在STL中的算法中一些算法是可以根据算法名字来判断算法作用的.所有算法的参数都是迭代器,不过不同的算法调用的迭代器类型也是不同的.多有的STL算法都作用在由迭代器{first,lase)所表示出来的区间上.拷贝(copy)交换(swap)替换(replace)填写(fill)删除(remove)排列组合(permutation)分割(partition)随机重排(random shuffling)排序(sort)计算(accumulate)计数(count)匹配(searc