STL Iterator的里里外外(一)?

STL Iterator的里里外外(一)?

1. Iterator是什么?

  Iterator是指针的概括物(泛型指针),是可以通过一组通用的接口类似于普通指针那样遍历区间中的所有元素的对象。Iterator是完全抽象的概念:任何行为类似于Iterator的东西就是一个Iterator(例如:指针是数组的迭代器)。

  Iterator是算法和数据结构(容器)之间的接口,被实现为一个智能指针,提供对operator*和operaor->等进行重载。但是不同的Iterator具有不同的能力,这就牵扯到了Iteratorde的分类。

2. Iterator分类

  

  Iterator具有5种分类,是5个concept的集合。

        Iterator Categories

  

  Input Iterator     OutputIterator

        Forward Iterator

       Bidirectional Iterator

      Random Access Iterator

  这5中分类决定了5种Iterator, 其中普通指针是Random access Iterator这个concept的一个modal。

  STL给了这5种Iterator一个tag用于标识这五种

  namespace std {

    //只有一种output

    struct output_iterator_tag {
    };

    //下面的所有都是一种input, 注意继承关系

  

    struct input_iterator_tag {
    }

    struct forward_iterator_tag  : public input_iterator_tag {
    }

    sturct bidirectional _iterator_tag : public forward_iterator_tag {
    }

    struct random_access_iterator_tag : public bidirctional_iterator_tag {
    }

  }

3. 各种Iterator的能力

3.1 Output iteator

  具有只写性质,适用于单回(single-pass)算法,如:copy。

  Input iterator的需求条件:

  (1)可以复制和赋值: Type(iter), copy constructor

   (2) 可以写值: *iter = val,但是不能读:val = *iter,val = iter->member;

   (3) 可以累加:++iter, iter++。

  注意:不支持 ==, !=, 唯一不支持的iterator。

  类似Input iterator,同一时间不能有两个不同的Output iterator指向同一个区间内的不同地点。移动中的指针进行写入,一旦写完遍继续移动。

  下面以copy算法来讲述:

  template <typename InputIterator, typename OutputIterator>

  OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)

  {

    for (  ; first != last; ++result, ++first) {

      *result = *first;
    }

    return result;
  }

  

  copy输入区间需要只读性质,输出区间需要只写性质,是与输入输出都有关的单回算法。

  Output Iterator 所形成的区间都是以单独一个Iterator再加上一个计量值来决定的。如copy: 输出区间以result开头,再以[first, last)的元素个数作为

区间的长度。

  

  

  Output iterator :有 insert_iterator, front_insert_iterator, back_insert_iterator和 ostream_iterator。

  ostream_iterator iter; *iter = val会使val格式化输出到ostream身上。

  template <class T>

  class ostrem_iterator {

  private:

    ostream *os;

    const char *string;

  public:

    ostrem_iterator(ostream &s, const char *c = 0) : os(&s), string(c) {}

    ostream_iterator(const ostream_iterator &i) : os(i.os), string(i.string) {}

    ostream_iterator& operator=(const ostream_iterator &i)

    {

      os = i.os;

      string = i.string;

      return *this;
    }

  

    ostream_iterator<T>& operator=(const T &value)  

    {

      *os << value;

      if (string)  {

        *os << string;
      }

      return *this;
    }

    //实现os << value; 替换为 *iter = val;使用proxy class, 而且是其自身*this,也可以使用其它class但是没理由这么做。

    ostream_iterator<T>& operator*() { return *this; }

    ostream_iterator<T>& operator++() { return *this; }

    ostream_iterator<T>& operator++(int) { return *this; }
  };

3.2 Input Iterator

  具有只读性质,适用于单回(single-pass)算法,如:copy。

  限制条件:

  (1)Input iterator用来指向某对象,但不需要提供任何更改该对象的方法, 就是只读的。

  你可以*或->,但是不能对结果赋值,即:*iter; iter->member可以,*iter = val(要求写)不一定可以。

  (2)Input iterator可以累加,但是不可以递减。

  可以++iter; iter++, 这是Input iterator唯一需要的运算形式。 不可以--iter; iter--。

  (3)Input iterator支持有限的比较形式,可以测试iter1 = iter2; iter1 != iter2; 但是不可以比较谁在谁前面。

  (4)Input iterator 是 single pass的,你有且只能遍历range(beg, end)一次。不能重复遍历。

  (5)Input iterator可以copy,支持copy constructor: TYPE(iter)。

  特点:

  Input iterator 只能读元素一次,如果使用iterator的副本和原始迭代器共同读,可能读取不同的值。典型的情况是从键盘读取输入,你不能读取两次。

  Input iterator 就像从终端机或网络连线读取数据一样的读取输入值:你可以要求下一个值,但一旦如此,前一个值就消失无踪了。使用Input iterator class

istream_iterator,可以简单的从input stream读取数据。

  使用Input iterator的算法:

  此算法必须是single pass(单回)的算法,只需要遍历区间一次读取值,不需要更改值的。常见有:

find, find_if, equal, partial_sum, random_sample, set_intersection等等。

3.3.  Forward Iterators

  缘起:

  (1) input iterator具只读性, output iterator 具只写性。意味着: 需要读取并更改的某一区间的算法,无法单就这些concept来运作。

可以利用input iterator写出某种查找算法,但是无法写出查找并置换的算法。

  (2) 运用input iterator和output iterator的算法,只能是single pass算法,使得算法的复杂度O(N)。

  (3)任何时刻,区间内只能有一个有效的input iterator或output iterator。使得算法在同一时刻只能对单一元素做动作。对于行为取决于两个或多个不同元素

之间的关系的算法无能为力。

  而采用Fordward iterator就不会有上述限制。一个Forward iterator model必须是input iterator model和output iterator model。

因此,可以写出一种算法在同一区间内做读取动作和更新动作。

  例如:replace()

  template <class ForwardIterator, class T>

  void replace(ForwardIterator first, ForwardIterator last,

          const T &old_value, const T &new_value)

  {

    for ( ; first != last; ++first) {

      if (*first == old_value) {

        *first = new_valude;
      }
    }
  }

  replace 是single pass算法,一次只作用一个元素,由于需要在同一个iterator上进行读取和更改,所以用Forward_iterato。

  Forward iterator也适用于在同一区间使用一个以上的iterator,是multipass的。

  //查找连续两个元素具有相同值

  template <class ForwardIterator>

  ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last)

  {

    if (first == last) {

      return last;
    }

    ForwardIterator next = first;

    while (++next != last) {

      if (*first == *next) {

        return first;
      }

      first = next;
    }

    return last;
  }  

  *first = *next;使用了两个Iterator所以用Forward_iterator。

  所以相比于Input iterator和Output iterator, forward_iterator提供了iter1 = iter2,因为它可以使用不同的Iteator。

  相关容器: forward_list<>, unordered containes。

3.4. Bidrectional Iterator

  类似于Forward Iterator,Bidirection iterator允许multipass,也可以是const或mutable。

  支持双向移动,因此相对于Forward_iterator支持--iter和iter--,如遍历单项链表用Forward Iterator,遍历双向链表用Bidirectiorn iterator。

  通常是由于需要反向移动而选择Bidirectional iterator, 即指定某元素之后需要寻找先前的元素。

  如:

  template <class BidrectionalIteartaor, class OutputIterator>

  OutputIterator reverse_copy(BidirctionalIterator first, Bidirctional last, OutputIterator result)

  {

    while (first != last) {

      --last;

      *result = *last;

      ++result;
    }

    return result;

  }

  需要--last;

  相关容器: class list<>, association containers。

3.5 Random Access Iterators

  提供了算术运算能力:iter + n, iter -n, iter[n], iter - iter2, iter < iter2,这些都是特有的。

  排序算法需要用到这个iterator,需要对比并交换相隔甚远的元素,而非只是相邻元素。

  考虑到Random Access Iterator主要是考虑到复杂度:

  例如:advance(), Forward Iterator是O(N), 而随机Iterator为O(1);

  所以:Random Access iterator正真独特的性质为:在固定时间随机访问任意元素。

  相关容器: array, vector, deque, string, wstring, C-style arrays(pointers)。

  

  

STL Iterator的里里外外(一)?

时间: 2024-07-30 21:13:49

STL Iterator的里里外外(一)?的相关文章

STL iterator和traits编程技法

今天终于看完了<STL源码分析>,最近忙于两个比赛的各种文档,没时间写东西,趁着看完的劲,把欠下的补上来. <Design patterns>中对于iterator模式描述如下:提供一种方法,使之能够依序寻访某个聚合物所含的各个元素,而又无需暴露该聚合物的内部结构.在STL中,iterator扮演着连接container和algorithms的作用,下面以STL find()函数展现一下iterator在container和algorithm之间的连接作用. template &l

STL iterator使用注意事项

当一个Container执行了一次earse操作之后,原来用来遍历的iterator就失效了,其行为是不可预测的,具体情况由实现决定. 同时earse操作会返回一个指向container下一个元素的iterator,如果想继续遍历,就得用返回的iterator继续操作. 如果只是删除遍历时候碰到的第一个符合条件的元素,那么在earse之后添加break,使得不再进行遍历.如果要继续操作,那么就得改成 for ( std::list<*>::iterator it =ObjList.begin(

STL源码分析-iterator(迭代器)

1. GOF 迭代器设计模式 前面一篇文章有写到stl_list的实现,也实现了一下相应的iterator,但是后面觉得,实现具体容器之前有必要介绍一下iterator(迭代器) .那么迭代器是什么呢? GOF的设计模式是这样定义的: 提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示. 大概意思是,例如一个聚合对象(list),我们该如何来访问它的元素,而又不暴露内部结构:而且还要针对不同的需要,可能以不同的方式遍历这个list:那么即使,我们知道大概会有哪些遍历操作,那

STL,ATL,WTL之间的联系和区别

一.STL即 Standard Template Library (标准模板库) STL是惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R Musser在惠普实验室工作时所开发出来的.现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间.STL的代码从广义上讲分为三类:algorithm(算法).container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于

C++ Standard Template Library STL(undone)

目录 1. C++标准模版库(Standard Template Library STL) 2. C++ STL容器 3. C++ STL 顺序性容器 4. C++ STL 关联式容器 5. C++ STL 容器适配器 6. C++ STL算法 7. C++ STL边界限制 1. C++标准模版库(STL) STL就是Standard Template Library,标准模板库.从根本上说 1. STL是一些"容器"集合 2. STL也是算法和其他一些组件的集合 3. 这里的&quo

【C/C++】STL,ATL,WTL之间的联系和区别

STL即 Standard Template Library (标准模板库) STL是惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R Musser在惠普实验室工作时所开发出来的.现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间.STL的代码从广义上讲分为三类:algorithm(算法).container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统

STL list链表的用法详解(转)

本文以List容器为例子,介绍了STL的基本内容,从容器到迭代器,再到普通函数,而且例子丰富,通俗易懂.不失为STL的入门文章,新手不容错过! 0 前言 1 定义一个list 2 使用list的成员函数push_back和push_front插入一个元素到list中 3 list的成员函数empty() 4 用for循环来处理list中的元素 5 用STL的通用算法for_each来处理list中的元素 6 用STL的通用算法count_if()来统计list中的元素个数 7 使用count_i

list容器详解

首先说说STL ( STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件.STL现在是C++的一部分,因此不用额外安装什么.它被内建在你的编译器之内.因为STL的list是一个简单的容器,所以我打算从它开始介绍STL如何使用.如果你懂得了这个概念,其他的就都没有问题了.另外,list容器是相当简单的,我们会看到这一点. STL容器可以保存对象,内建对象和类对象.它们会安全的保存对象,并定义我们能够操作的这个对象的接口.放在蛋架上的鸡蛋不会滚到桌上.它们很安全.因此,在STL容器中的对

VS2010下编译配置Boost_1.53

一.准备工作 1.下载最新版本的boost库.所在地址:boost_1_53_0.zip.官方推荐7z压缩格式的,因为其压缩效率更好,相应包的大小也比较小. 2.解压缩到指定目录,如C:\boost_1_53.下面开始遵照官方页面的步骤进行编译.() 进入目录tools\build\v2\ 运行bootstrap.bat脚本文件 运行命令:b2 install --prefix=PREFIX.其中PREFIX是为Boost.Build指定的安装目录,生成的编译工具将会存放在该目录下.我指定为c: