C/C++容器和迭代器理解

  转载自:

    https://blog.csdn.net/summerxiachen/article/details/59538640

 

为什么要有容器?

   我知道有数组,但数组有一个弊端,它是固定的,不可变。这个经常会导致出现数组越界导常的错误。并且还需要事先知道这个数组的长度才可以定义。 但很多时候,我们并不知道未来将会发生什么,所以我们创造了容器,它是不固定的,可变的,可以根据元素的增加而增加,每次增加原数组的1.5倍。为什么是1.5倍呢,因为2倍太大了,1倍太小,所以为了保证效率,择中选1.5倍。

数组与容器的区别?
数组能存基础数据类型,也可以存引用数据类型;容器只能存引用数据类型数组的长度是固定的,容器的长度可以根据元素的增加而增加

为什么会有迭代器?
数组有的功能,容器大部分都会有。数组存放数据可能是有序的,也可能是无序的。所以容器也具备同样的功能,容器英文:Collection,有序的表示为List,即链表结构,无序的表示为Set,即想在哪建立就在哪建立。问题来了,有序的List,我们可以通过索引来遍历数组。但无序的Set怎么办?用一句话总结:Iterator类的访问方式就是把不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循环遍历集合的效果。
(附上C++容器和迭代器 ppt

在学习c++ STL的时候,整天碰到迭代器,也整天用,但是,到底它是个什么东西,很多人没有一个认识。这里我通过几个小的DEMO,来看看迭代器。首先我实现了一个十分简陋的vector类:
[cpp] view plain copy
 
  1. template <class T>    
  2.     class vector {    
  3.     private:    
  4.         T* pbegin;    
  5.         int n; //当前大小    
  6.     public:    
  7.         vector() {    
  8.             pbegin = new T[100]; //暂时先固定大小    
  9.             n = 0;    
  10.         }    
  11.             
  12.         T* begin() {    
  13.             return pbegin;    
  14.         }    
  15.         void insert(T d){    
  16.             pbegin[n++] = d;    
  17.         }    
  18.         typedef T* iterator; //vector的迭代器就是基础指针类型    
  19.     };    


我们知道,vector是数组实现的,也就是说,只要知道数组的首地址,就能知道后面每个元素的位置,所以,访问vector的迭代器,其实就是一个基础的指针类型,我们可以通过++,--等操作,来遍历访问该vector。
[cpp] view plain copy
 
  1. //测试vector    
  2.         vector<int> a;    
  3.         a.insert(1);    
  4.         a.insert(2);    
  5.         vector<int>::iterator itra;    
  6.         itra = a.begin();    
  7.         printf("%d/n", *itra);     
  8.         itra++;    
  9.         printf("%d/n", *itra);    
  10.         itra--; //基础指针类型都支持++,--,+,-等操作符    
  11.         printf("%d/n", *itra);    


哇~~,原来vector的迭代器那么简单,那么,我们来考虑一下List,这是链表,我们知道,链表每个元素都存储在不同的位置,我们一般通过指向下一个元素的next指针来找到下一个元素。那么,我们怎么样来设计一个迭代器,然后可以直接对这个迭代器进行++,--等操作二遍历访问整个链表呢:

[cpp] view plain copy
 
  1. template <class T>    
  2.     class List{    
  3.     private:    
  4.         struct Node{ //链表的节点    
  5.             T data;    
  6.             Node* next;    
  7.         };    
  8.         Node* pbegin; //表头    
  9.         class List_iterator{ //链表的迭代器    
  10.             Node* cur; //当前指向    
  11.         public:    
  12.             void operator = (Node* ptr) {    
  13.                 cur = ptr;    
  14.             }    
  15.             void operator ++ () {    
  16.                 cur = cur->next;    
  17.             }    
  18.             // ...还可以重载-- + -等操作符    
  19.             T operator * (){    
  20.                 return cur->data;    
  21.             }    
  22.         };    
  23.     public :    
  24.         List() {    
  25.             pbegin=NULL;    
  26.         }    
  27.         Node* begin() {    
  28.             return pbegin;    
  29.         }    
  30.         void insert(T d) {    
  31.             Node* p=pbegin;    
  32.             while(p && p->next) p=p->next;    
  33.             Node* t = new Node;    
  34.             t->data = d;    
  35.             t->next = NULL;    
  36.             if(pbegin==NULL)    
  37.                 pbegin = t;    
  38.             else    
  39.                 p->next = t;    
  40.         }    
  41.         typedef List_iterator iterator; //List的迭代器是一个类    
  42.     };    


为List设计的迭代器是一个类,这个类支持++操作来向后移动遍历链表:

[cpp] view plain copy
 
  1. //测试List    
  2.         List<int> b;    
  3.         b.insert(1);    
  4.         b.insert(2);    
  5.         List<int>::iterator itrb;    
  6.         itrb = b.begin();    
  7.         printf("%d/n", *itrb);    
  8.         itrb++; // 该迭代器只支持++    
  9.         printf("%d/n", *itrb);    


通过这两个例子,可以看出,迭代器是跟容器紧密结合的,不同的容器,它的迭代器不同,但是,他们有共同的目标,就是可以通过该迭代器,来遍历访问这个容器里面的元素。这样带来的好处是在STL设计算法时,可以脱离容器而设计更加通用的算法。比如,在容器中查找一个元素。查找,这个操作一般来说就是遍历整个集合,然后找到那个要找的元素,但是,如果没有迭代器,我们需要为vector和List设计两个查找算法,因为找下一个元素在vector和List中的操作不同。同样的思想却要两套代码,显然这是不优秀的。

      有了模板,我们可以将算法和特定的数据分离开来,而有了迭代器,我们可以将算法和特定的容器分离开来。

posted @ 2018-05-08 00:32  博客园—哆啦A梦  阅读(1209)  评论(0)    收藏  举报