模板编程-迭代器

迭代器ios

迭代器源于指针而高于指针,并成为分割容器与算法的一条界河.在一个共同的迭代器界面约定之下,不一样的算法与不一样的容器只要其迭代器要求一致就能够相互组合.c++

 

迭代器分类算法

c++标准库中对迭代器进行了详细的分类,迭代器按其所能提供的操做,能够分为五种类型,分别为:dom

    输入迭代器(input iterator) > 前向迭代器(forward iterator) > 双向迭代器(bidirectional iterator) > 跳转迭代器(random access iterator)以及输出迭代器(output iterator).
函数

后者是前者的子集.输入迭代器提供的操做最少,只支持当前位置数据及前进一位。而跳转迭代器的功能最为丰富,不只支持取数据,还能够前进或者后退多位。输出迭代器支持向所指位置写入数据。this

 

1.输入迭代器与前向迭代器的区别.spa

前向迭代器与输入迭代器的要求极为类似,除去构造函数及比较操做外,两者都提供自加1操做前移一位以及去引用取值.而最关键的区别在于,前向迭代器可以保证两个迭代器实例a与b,若是a==b,则必定也知足++a=++b,而输入迭代器不能保证这一点.指针

例子:code

 1 #include <iostream>
 2 #include <stack>
 3 
 4 template<typename Stack>
 5 class stack_iterator{
 6 public:
 7      typedef typename Stack::value_type value_type;
 8      typedef typename Stack::reference reference;
 9          
10 private:
11       Stack &s;
12       value_type *pos;
13 public:
14       stack_iterator(Stack &_s):s(_s),pos(_s.size()?_s.top():0){}
15       reference operator *() const{return *pos;}
16       stack_iterator& operator++ (){
17           s.pop();
18           pos=s.size()?&s.top():0;
19           return *this;
20       }
21       
22       bool operator ==(stack_iterator const& rhs) const {return pos==rhs.pos;}
23       bool operator !=(stack_iterator const& rhs) const {return pos!=rhs.pos;}
24 };
25 
26 int main(){
27     using namespace std;
28     int numbers[]={0,1,2,3,4};
29     typedef stack<int> int_stack;
30     int_stack s;
31     
32     for(int i=0;i<5;i++) s.push(numbers[i]);
33     
34     stack_iterator<int_stack> a(s);
35     stack_iterator<int_stack> b(s);
36     
37     cout<<((a==b)?"a"==b"?"a!=b")<<endl;
38     ++a;++b;
39     cout<<((a==b)?"++a==++b":"++a!=++b")<<endl;
40     
41     coout<<*a<<endl;//危险操做,a所指数据已经出栈,空间已被释放
42 }

 

从中咱们能够体会到对输入迭代器的自加1操做的意义.一旦某迭代器经过自加1操做前移一位后,则全部指向以前的迭代器不能保证仍然有效,因此迭代器的前移不是破坏了容器中的数据至少也是屏蔽了以前的数据.而基于前向迭代器的算法则不一样,虽然前向迭代器只能前移,可是能够保证a==b能够得出++a==++b,故能够经过保存迭代器的多个副原本实现屡次遍历.blog

 

以标准库中容器所提供的迭代器为例。vector、deque及array都能提供可写跳转迭代器。list能提供可写双向迭代器。forward_list能提供可写前向迭代器。set和multiset能提供只读双向迭代器。map和multimap能提供只读双向迭代器.

 

二:迭代器属性类模板

迭代器除了要提供必要的操做外,还应该包含足够的信息以描述其自身的属性,如所属迭代器类型、所指数据等.通常而言,相关属性都是经过在迭代器类型中嵌套定义类型来定实现的.所以,在标准中特别定义了一个模板类std::iterator_traits<T>为算法提取迭代器各类属性之用.

标准中为迭代器规定了五个属性:

  • difference_type (迭代器差值类型)
  • value_type(迭代器所指数据类型)
  • pointer(数据指针类型)
  • reference(数据引用类型)
  • 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,做者能够根据迭代器类型采起不一样的策略.

 1 //适用于前向迭代器的advance函数实现,n次加1操做
 2 template <typename I>
 3 void advance_impl(I &i,typename std::iterator_traits<I>::difference_type n,
 4                                     std::forward_iterator_tag){
 5         for(;n>0;n--) i++;
 6 }
 7 
 8 //适用于跳转迭代器的advance函数实现,直接用i+=n
 9 template <typename I>
10 void advance_impl(I &i,typename std::iterator_traits<I>::difference_type n,
11                                      std::random_access_iterator_tag){
12      i+=n;                                         
13 }
14 
15 template <typename I>
16 void advance(I &i,typename I::difference_type n){
17        //以iterator_category()为哑参数指导编译器选择适当的重载实现
18        advance_impl(i,n,typename std::iterator_traits<I>::iterator_category());
19 }
相关文章
相关标签/搜索