《STL源码剖析》学习笔记系列之三-------迭代器和traits编程
迭代器iterator的模式:提供一种方法,使之能够依序巡防某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表达方式。迭代器起着算法和容器的粘合剂,算法通过迭代器操作容器内部的数据。
1、 template参数推导机制
1、 template <class T>
2、 inline const T& Min(const T& a,const T& b) {
3、 return b < a ? b : a;
4、 }
5、 int main()
6、 {
7、 cout<<Min(1,2)<<endl;
8、 cout<<Min(1.2,3.2)<<endl;
9、 return0;
10、 }
在主函数中,调用Min()函数时,编译器会根据实参实例化两个Min()函数,即编译器推导出模板参数相应的型别。如下所示:
11、 inline const int& Min(const int&a, const int& b)
12、 {
13、 return b < a ? b : a;
14、 }
15、 inline const double& Min(constdouble& a, const double& b)
16、 {
17、 return b < a ? b : a;
18、 }
2、 声明内嵌型别
1、 #include <iostream>
2、 usingnamespace std;
3、
4、 template<class T>
5、 struct MyIter
6、 {
7、 typedef T value_type; // value_type定义 内嵌型别声明
8、 T* ptr;
9、 MyIter(T* p=0): ptr(p){}
10、 T& operator*()const{return*ptr;}
11、 };
12、
13、 template<class I>
14、 typename I::value_type//返回值类型 typename用于指明I::value_type是个类型
15、 func(I ite)
16、 {
17、 return*ite;
18、 }
19、
20、 int main(int argc, char**argv)
21、 {
22、 MyIter<int> ite(newint(8));
23、 cout<< func(ite)<< endl;
24、
25、 return0;
26、 }
27、 // 输出8
第9行声明了一个内嵌型别,第16行用于对func函数的返回标明该函数的返回值类型。此方法不使用原生指针,原生指针无法添加一个value_type的内嵌类型。
3、 类型信息‘榨取机’-traits: 获取迭代器的特性
28、 template <typename T>
29、 struct iterator_traits
30、 {
31、 typedef typename T::value_typevalue_type;
32、 };
这样,我们可以通过 Traits<myIte>::value_type 来获得myIte的value_type。
33、 template<class I>
34、 typenameiterator_traits<I>::value_type
35、 func(I ite)
36、 {
37、 return*ite;
38、 }
4、 偏特化:解决原生指针的问题
39、 template <typename T>
40、 struct iterator_traits<T*> //注意这里针对原生指针进行了偏特化
41、 {
42、 typedef T value_type;
43、 };
//指向常数对象的指针
44、 template <typename T>
45、 struct iterator_traits<const T*> //注意这里针对原生指针进行了偏特化
46、 {
47、 typedef T value_type;
48、 };
5、 迭代器的型别:即迭代器的特性(属性)
1、value type:指迭代器所指对象的型别
2、difference type: 表示两个迭代器之间的距离,也可用来表示一个容器的最大容量。
3、reference type: 表示迭代器所指数据的引用类别
4、pointer type: 表示迭代器所指数据的指针类型
5、iterator_category:表示迭代器所属的类型,共有5类。
1. //通常迭代器的几种特性被放在iterator_traits
2. template <class Iterator>
3. struct iterator_traits {
4. typedef typename Iterator::iterator_category iterator_category;
5. typedef typename Iterator::value_type value_type;
6. typedef typename Iterator::difference_type difference_type;
7. typedef typename Iterator::pointer pointer;
8. typedef typename Iterator::reference reference;
9. };
6、 迭代器的类型
1、Input Iterator: 此迭代器不允许修改所指的对象,即是只读的。支持==、!=、++、*、->等操作。
2、OutputIterator: 允许算法在这种迭代器所形成的区间上进行只写操作。支持++、*等操作。
3、ForwardIterator: 允许算法在这种迭代器所形成的区间上进行读写操作,但只能单向移动,每次只能移动一步。支持Input Iterator和Output Iterator的所有操作。
4、BidirectionalIterator: 允许算法在这种迭代器所形成的区间上进行读写操作,可双向移动,每次只能移动一步。支持Forward Iterator的所有操作,并另外支持--操作。
5、 RandomAccess Iterator: 包含指针的所有操作,可进行随机访问,随意移动指定的步数。支持前面四种Iterator的所有操作,并另外支持it + n、it - n、it += n、 it -= n、it1 - it2和it[n]等操作。
由上图可知,各类型迭代器的分类与从属关系。为了提供最大化的执行效率,STL在设计算法时,会尽量提供一个最明确最合适的迭代器,在完成任务的同时,也尽量提高算法的效率。
假设有个算法可接受Forward Iterator,此时,你可以传入一个Random Access Iterator,因为RandomAccess Iterator也是一种Forward Iterator,但是可用并不代表最合适,我们只需要Forward Iterator的功能,却传入了更多属于Random Access Iterator的在这里没有用到的功能,一定程度上会降低了算法的效率。
参考文献:
http://blog.csdn.net/shudou/article/details/10270971
http://blog.csdn.net/lonelywinter340/article/details/3327700
http://www.programlife.net/stl-iterator.html