STL--迭代器--原理与实践
来源:互联网 发布:课堂随机点名软件 编辑:程序博客网 时间:2024/06/16 13:42
迭代器(iterator
)是STL
里面很基础也很重要的一个东西,迭代器的traits
技术设计的很棒。
迭代器是一种行为类似指针的对象,因为指针最常用的是->
和*
两个操作符,因此迭代器最重要的编程工作也是对这两个操作符的重载的实现。
初探traits技术
假设现在定义了这样一个迭代器MyIter
,当我们拿到一个MyIter
对象时,如何判断他的类型呢?
template<class T>struct MyIter{ T* ptr; MyIter(T* p=0) : ptr(p) {} T& operator*() const { return *ptr; }};MyIter<int> iter(new int(1));// What's type of *iter ???
在STL
的实现中,给MyIter
添加了一个value_type
的定义,然后通过MyIter::value_type
取得对应的类型,这就是所谓的traits
技术了。
#include <iostream>using namespace std;template<class T>struct MyIter{ typedef T value_type; // value_type定义 T* ptr; MyIter(T* p=0) : ptr(p) {} T& operator*() const { return *ptr; }};template<class I>typename I::value_type // typename用于指明I::value_type是个类型, 并且作为返回值类型func(I ite){ return *ite;}int main(int argc, char **argv){ MyIter<int> ite(new int(8)); //定义了一个对象,模板参数是int, 对象中的ptr指针指向了数值8 cout << func(ite) << endl; // return 0;}// 输出8
函数模板中的参数类型I
是 MyIter
, 函数返回值类型是MyIter::value_type
, return *ite
即使执行重载后的*
返回值.
使用萃取技术,那么函数可以针对任意返回类型都是允许的,因为传递给函数的参数是迭代器(指针),萃取技术就是从迭代器类型(迭代器类)中获取返回值的类型。
迭代器类的构造是通过指定的模版参数值类型int
构造的.
上面的代码中通过模板参数的value_type
来推导出具体的类型,注意typename
用于指明I::value_type
是个类型,如果没有typename
的话,编译器将把value_type
当成I
的一个member
或者member function
。
问题:既然说迭代器是一种智能指针,那么func
对于普通的原始指针也应该是可用的,但是普通的原始指针不是对象,并不不具备value_type
这内嵌类型的定义,解决之道就是使用偏特化技术(partial specialization
)。
模板特化
C++
模板的分两种:偏特化和全特化(所谓偏特化是指部分特化)。
特化(或者说全特化,specialized
)不过是一个花哨的术语,意思是形参不再为形参,它们已经有了确定的值;而偏特化(partial specialization
)的意思是提供另一份template
的定义,其本身仍然是一个template
,或者说针对template
参数更进一步的条件限制所设计出来的一个特化版本。
#include <iostream>using namespace std;// traits模板的定义template<class I>struct my_traits{ typedef typename I::value_type value_type;};// 针对T*的偏特化版本template<class T>struct my_traits<T*>{ typedef T value_type;};// 针对const T*的偏特化版本template<class T>struct my_traits<const T*>{ typedef T value_type;};// MyIter定义template<class T>struct MyIter{ typedef T value_type; T* ptr; MyIter(T* p=0) : ptr(p) {} T& operator*() const { return *ptr; }};// func函数模板,注意返回类型为typename my_traits<I>::value_typetemplate<class I>typename my_traits<I>::value_typefunc(I ite){ return *ite;}int main(int argc, char **argv){ MyIter<int> ite(new int(8)); cout << func(ite) << endl; int *p = new int(1); const int *pc = new int(2); cout << func(p) << endl; cout << func(pc) << endl; return 0;}// 输出8 1 2
经过添加模板偏特化版本的定义之后,func
对于原始指针也可以支持了。本文重点描述迭代器相关特性,所以关于特化的更多介绍,请自行搜索相关资料。
迭代器基本框架
按照约定,迭代器需要定义5个内嵌类型:iterator_category
、value_type
、difference_type
、pointer
、reference
。
template <class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&>struct iterator { typedef Category iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference;};
也就是萃取出来模版参数的类型………………………
这些类型所表示的意义如下:
value type
用来表示迭代器所指对象的型别; difference type
用来表示两个迭代器之间的距离; reference
为引用类型; pointer
为指针类型; iterator_category
表明迭代器的类型;
根据迭代器移动特性与施行动作,迭代器被分为五类:
Input Iterator
:这种迭代器所指对象,不允许外界改变,只读(read only
);Output Iterator
:唯写(write only
);Forward Iterator
:允许「写入型」算法(例如replace()
)在此种迭代器所形成的区间上做读写动作;Bidirectional Iterator
:可双向移动。某些算法需要逆向走访某个迭代器区间(例如逆向拷贝某范围内的元素),就可以使用Bidirectional Iterators
;Random Access Iterator
:前四种迭代器都只供应一部份指标算术能力(前3
种支持operator++
,第4种再加上operator–-
),第5种则涵盖所有指标算术能力,包括p+n
,p-n
,p[n]
,p1-p2
,p1
.
几种迭代器之间的关系图:
iterator源码
#ifndef __SGI_STL_INTERNAL_ITERATOR_BASE_H#define __SGI_STL_INTERNAL_ITERATOR_BASE_H#include <concept_checks.h>__STL_BEGIN_NAMESPACE// 五种迭代器tag的定义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 {};// input_iterator 定义template <class _Tp, class _Distance> struct input_iterator { // 类别为 input_iterator_tag typedef input_iterator_tag iterator_category; typedef _Tp value_type; typedef _Distance difference_type; typedef _Tp* pointer; typedef _Tp& reference;};// output_iterator 定义struct output_iterator { // 类别为 output_iterator_tag typedef output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference;};template <class _Tp, class _Distance> struct forward_iterator { typedef forward_iterator_tag iterator_category; // ...};template <class _Tp, class _Distance> struct bidirectional_iterator { typedef bidirectional_iterator_tag iterator_category; // ...};template <class _Tp, class _Distance> struct random_access_iterator { typedef random_access_iterator_tag iterator_category; // ...};#ifdef __STL_USE_NAMESPACES// iterator 定义template <class _Category, class _Tp, class _Distance = ptrdiff_t, class _Pointer = _Tp*, class _Reference = _Tp&>struct iterator { typedef _Category iterator_category; typedef _Tp value_type; typedef _Distance difference_type; typedef _Pointer pointer; typedef _Reference reference;};#endif /* __STL_USE_NAMESPACES */// 偏特化#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION// iterator_traits 模板template <class _Iterator>struct iterator_traits { typedef typename _Iterator::iterator_category iterator_category; typedef typename _Iterator::value_type value_type; typedef typename _Iterator::difference_type difference_type; typedef typename _Iterator::pointer pointer; typedef typename _Iterator::reference reference;};// iterator_traits 针对指针的特化版本template <class _Tp>struct iterator_traits<_Tp*> { typedef random_access_iterator_tag iterator_category; typedef _Tp value_type; typedef ptrdiff_t difference_type; typedef _Tp* pointer; typedef _Tp& reference;};// iterator_traits 针对const指针的特化版本template <class _Tp>struct iterator_traits<const _Tp*> { typedef random_access_iterator_tag iterator_category; typedef _Tp value_type; typedef ptrdiff_t difference_type; typedef const _Tp* pointer; typedef const _Tp& reference;};// 获取迭代器的类型 (返回一个该类型的对象)template <class _Iter>inline typename iterator_traits<_Iter>::iterator_category__iterator_category(const _Iter&){ typedef typename iterator_traits<_Iter>::iterator_category _Category; return _Category();}// 获取迭代器的 __distance_typetemplate <class _Iter>inline typename iterator_traits<_Iter>::difference_type*__distance_type(const _Iter&){ return static_cast<typename iterator_traits<_Iter>::difference_type*>(0);}// 获取迭代器的 __value_typetemplate <class _Iter>inline typename iterator_traits<_Iter>::value_type*__value_type(const _Iter&){ return static_cast<typename iterator_traits<_Iter>::value_type*>(0);}// __iterator_category 的const参数版本template <class _Iter>inline typename iterator_traits<_Iter>::iterator_categoryiterator_category(const _Iter& __i) { return __iterator_category(__i); }// __distance_type 的const参数版本template <class _Iter>inline typename iterator_traits<_Iter>::difference_type*distance_type(const _Iter& __i) { return __distance_type(__i); }// __value_type 的const参数版本template <class _Iter>inline typename iterator_traits<_Iter>::value_type*value_type(const _Iter& __i) { return __value_type(__i); }#define __ITERATOR_CATEGORY(__i) __iterator_category(__i)#define __DISTANCE_TYPE(__i) __distance_type(__i)#define __VALUE_TYPE(__i) __value_type(__i)#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */// 如果不支持偏特化,那么就需要定义iterator_category的函数重载的形式了// 这里略去了此部分源代码的解释,因为估计也只有{非主流}编译器才不支持偏特化吧#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */// 体验traits技术的威力,针对不同的迭代器类型定义不同的distance实现版本// _InputIterator 版本template <class _InputIterator, class _Distance>inline void __distance(_InputIterator __first, _InputIterator __last, _Distance& __n, input_iterator_tag){ while (__first != __last) { ++__first; ++__n; }}// _RandomAccessIterator版本template <class _RandomAccessIterator, class _Distance>inline void __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, _Distance& __n, random_access_iterator_tag){ __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); __n += __last - __first;}// distance 接口// 注意 _RandomAccessIterator 也是 _InputIteratortemplate <class _InputIterator, class _Distance>inline void distance(_InputIterator __first, _InputIterator __last, _Distance& __n){ __STL_REQUIRES(_InputIterator, _InputIterator); // 通过 iterator_category 取得迭代器类型 __distance(__first, __last, __n, iterator_category(__first));}#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION// 对_Distance进行了特化template <class _InputIterator>inline typename iterator_traits<_InputIterator>::difference_type__distance(_InputIterator __first, _InputIterator __last, input_iterator_tag){ typename iterator_traits<_InputIterator>::difference_type __n = 0; while (__first != __last) { ++__first; ++__n; } return __n;}template <class _RandomAccessIterator>inline typename iterator_traits<_RandomAccessIterator>::difference_type__distance(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) { __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); return __last - __first;}template <class _InputIterator>inline typename iterator_traits<_InputIterator>::difference_typedistance(_InputIterator __first, _InputIterator __last) { typedef typename iterator_traits<_InputIterator>::iterator_category _Category; __STL_REQUIRES(_InputIterator, _InputIterator); return __distance(__first, __last, _Category());}#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */// 体验traits技术的威力,针对不同的迭代器类型定义不同的advance实现版本// _InputIterator 版本template <class _InputIter, class _Distance>inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) { while (__n--) ++__i;}#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)#pragma set woff 1183#endif// _BidirectionalIterator 之前前进与后退template <class _BidirectionalIterator, class _Distance>inline void __advance(_BidirectionalIterator& __i, _Distance __n, bidirectional_iterator_tag) { __STL_REQUIRES(_BidirectionalIterator, _BidirectionalIterator); if (__n >= 0) while (__n--) ++__i; else while (__n++) --__i;}#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)#pragma reset woff 1183#endif// _RandomAccessIterator版本template <class _RandomAccessIterator, class _Distance>inline void __advance(_RandomAccessIterator& __i, _Distance __n, random_access_iterator_tag) { __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); __i += __n;}// advance 接口template <class _InputIterator, class _Distance>inline void advance(_InputIterator& __i, _Distance __n) { __STL_REQUIRES(_InputIterator, _InputIterator); __advance(__i, __n, iterator_category(__i));}__STL_END_NAMESPACE#endif /* __SGI_STL_INTERNAL_ITERATOR_BASE_H */
代码中有distance
和advance
两个函数,通过traits
技术自动使用最佳的实现函数。
__type_traits
除了iterator_traits
采用了traits
技术外,还有一个叫做__type_traits
的东西.
// 模拟true和false定义的两个空类型struct __true_type {};struct __false_type {};template <class _Tp>struct __type_traits { typedef __true_type this_dummy_member_must_be_first; // 默认都是返回__false_type // 无意义的构造函数 typedef __false_type has_trivial_default_constructor; // 无意义的复制构造函数 typedef __false_type has_trivial_copy_constructor; // 无意义的赋值操作符 typedef __false_type has_trivial_assignment_operator; // 无意义的析构函数 typedef __false_type has_trivial_destructor; // 是否是POD类型 typedef __false_type is_POD_type;};// #define __STL_TEMPLATE_NULL template<>// 这里定义的都是全特化版本__STL_TEMPLATE_NULL struct __type_traits<char> { typedef __true_type has_trivial_default_constructor; typedef __true_type has_trivial_copy_constructor; typedef __true_type has_trivial_assignment_operator; typedef __true_type has_trivial_destructor; typedef __true_type is_POD_type;};// ...// 用于判断一个函数是否是整数类型template <class _Tp> struct _Is_integer { // 默认不是整数类型 typedef __false_type _Integral;};// 全特化版本__STL_TEMPLATE_NULL struct _Is_integer<char> { typedef __true_type _Integral;};
迭代器设计模式
迭代器模式是GoF
提出的23中设计模式之一,**迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。就如刚接触map/set
等关联容器的时候,我们能够通过迭代器访问所有容器元素,却不知道容器是用红黑树实现的一样。
迭代器模式的类图结构如下:
- STL--迭代器--原理与实践
- [Struts]原理与实践
- Struts原理与实践 - -
- IPSec原理与实践
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践 - -
- Struts原理与实践
- Struts原理与实践
- Struts原理与实践
- IPSec原理与实践
- DialogFragment实践与原理
- 密码学原理与实践
- TBSchedule原理与实践
- TBSchedule原理与实践
- 从一个菜鸟开始学习机器学习
- 【HDU】5221 Occupation【树链剖分】
- 流随机访问
- Windows版OpenVPN安装、配置教程
- Ruby七天入门(2 函数,数组和类)
- STL--迭代器--原理与实践
- 网络营销公司,一站式网络营销服务
- android点滴
- Unity3D的断点调试功能
- 不要过早的释放动态内存空间
- java 中文乱码 总结
- CUDA学习笔记之 CUDA存储器模型
- c++之拷贝构造函数
- Python图像处理PIL模块