迭代器,旨在提供一种方法,使得依次访问某容器内的各个元素,而又不需要暴露出该容器的内部表达方式。迭代器不是指针,是类模板,表现得像指针:迭代器返回额是对象引用而不是对象的值。
2、迭代器的几个型别- 值类型
- 差值类型
- 引用类型
- 指针类型
- 迭代器类型(包括单向迭代器、随即迭代器、双向迭代器)
– [1] input_iterator;//只读迭代器
– [2] output_interator;//只写迭代器
– [3] Forward_iterator;//正向迭代器
– [4] Bidirectional_iterator;//双向迭代器
– [5] Random_Access_iterator;//随机迭代器
以vector容器为例:
#include#include using namespace std; //模板函数 template void print(_T con) { for(typename _T::const_iterator it=con.begin();it!=con.end();++it) { cout<<*it<<" "; } cout< //vector 随机迭代器 vector vec; for(int i=0;i<5;++i) { vec.push_back(i); } //只能读取容器中的元素,不可修改 vector ::const_iterator it=vec.begin(); for( ; it!=vec.end();it++) { cout<<*it<<" "; // 0 1 2 3 4 } cout< ::iterator it2 =vec.begin(); for( ; it2!=vec.end();++it2) { *it2=5;//使用 * 访问迭代器所指向的元素 cout<<*it2<<" "; // 5 5 5 5 5 } cout< ::iterator newiter=vec.begin(); vector ::iterator newiter2=vec.end(); cout< 迭代器的差值:
4、迭代器失效问题std::distance(start_id,end_it);//表示了元素个数
随机迭代器适用:直接相减,其他类型别的迭代器就需要逐个计数5、迭代器的萃取
- 对于顺序容器vector,deque来讲,在进行删除erase()操作后,后边的每个元素的迭代器都会失效,后边的每个元素都会往前移动,erase()返回下一个有效的迭代器。
- 对于关联容器map,set来讲,进行删除erase()后,当前元素的迭代器失效,但因为其底层结构是红黑树,删除当前元素,并不会影响下一元素的迭代器,所以在调用erase()前,记录一下下一元素的迭代器即可。
- 对于list,它使用了不连续的内存分配,并且其erase()也返回下一个有效的迭代器,因此,上面两种方式都可以。
首先,先看看STL的迭代器的源码是怎么写的:
typedef int ptrdiffer_t;//差值类型 struct intput_iterator_tag{}; //只读迭代器 struct output_interator_tag{}; //可写迭代器 struct forward_iterator_tag{}; //正向迭代器 struct bidirection_iterator_tag{}; //随机迭代器 templatestruct iterator { typedef _C iterator_category;//迭代器的类型 typedef _Ty value_type; //迭代器所迭代的数据的类型 typedef _D difference_type;//差值 typedef _Pointer pointer;//指针 typedef _Reference reference;//引用类型 }; //类型萃取器 template struct iterator_traits { iterator_traits() {} typedef typename _Iterator::iterator_category iterator_category; typedef typename _Iterator::value_type value_type; typedef typename _Iterator::difference_type differce_type; typedef typename _Iterator::pointer pointer; typedef typename _Iterator::reference reference; }; template struct iterator_traits { iterator_traits() {} typedef typename random_access_iterator_tag iterator_category; typedef typename T value_type; typedef typename int differce_type; typedef typename T * pointer; typedef typename T& reference; }; template struct iterator_traits { iterator_traits() {} typedef typename random_access_iterator_tag iterator_category; typedef typename T value_type; typedef typename int differce_type; typedef typename const T* pointer; typedef typename const T& reference; }; /// SGI template inline typename iterator_traits<_II>::iterator_category iterator_category(const _II&) { typedef typename iterator_traits<_II>::iterator_category cate; return cate(); } template inline typename iterator_traits<_II>::value_type * value_type(const _II&) { return static_cast ::value_type*>(0); } template inline typename iterator_traits<_II>::difference_type* difference_type(const _II&) { return static_cast ::difference_type*> (0); } // 正向迭代器 template struct _Forit :public iterator {}; // 双向迭代器 template struct _Bidit :public iterator {}; // 随机迭代器 template struct _Ranit :public iterator< random_access_iterator_tag, _Ty, _D> {}; template inline void __advance(_II& i, _D n, input_iterator_tag) { while (n--) ++i; } template inline void __advance(_BI & i, _D n, bidirectional_iterator_tag) { if (n >= 0) { while (n--) ++i; } else { while (n++) --i; } } template inline void __advance(_RAI& i, _D n, random_access_iterator_tag) { i += n; } template inline void advance(_II& i, _D n) { //iterator_traits<_II>(); //typedef typename iterator_traits<_II>::iterator_category cate; __advance(i, n, iterator_category(i)); } template inline typename iterator_traits<_II>::difference_type __distance(_II _F, _II _L, input_iterator_tag) { typename iterator_traits<_II>::difference_type n = 0; while (_F != _L) { _F++; n++; } return n; } template inline typename iterator_traits<_RAI>::difference_type __distance(_RAI _F, _RAI _L, random_access_iterator_tag) { return _L - _F; } template inline typename iterator_traits<_II>::difference_type distance(_II _F, _II _L) { return __disstance(_F, _L, iterator_category(_F)); } 现在,来理解一下,迭代器是如何萃取到容器类型:
其实,从这里我们可以知道,迭代器的类型萃取是在编译时期就可以确定迭代器的类型了的。之前我们还提到过,构造函数和析构函数的是否有关紧要,极大地影响了对象的创建与析构的代码的运行效率,所以用到类型萃取之后,编译器就会自动找到对应的函数来执行,以提高效率。
下一节:空间配置器...



