zoukankan      html  css  js  c++  java
  • 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的迭代器类型为双向迭代器。

    ![](https://img2018.cnblogs.com/blog/1285081/201809/1285081-20180925233604703-939646533.png)

    迭代器作为STL的一个重要组成部分,今天算是做了一个简单的总结,在后续分析STL其他内容的过程中也会经常遇到!

    2018年9月25日23:44:02

  • 相关阅读:
    Rainmeter 雨滴桌面 主题分享
    行人检測之HOG特征(Histograms of Oriented Gradients)
    const和readonly差别
    ADB命令解析
    Java实现 蓝桥杯VIP 算法训练 接水问题
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
  • 原文地址:https://www.cnblogs.com/blog-yejy/p/9704114.html
Copyright © 2011-2022 走看看