STL笔记(7)——Traits编程技法(二)
来源:互联网 发布:淘宝手机拍照技巧集锦 编辑:程序博客网 时间:2024/06/05 09:22
STL笔记(7)——Traits编程技法(二)
迭代器型别
五种迭代器型别:
- value_type
- different_type
- pointer
- reference
- iterator_category
前四个比较简单,分别是: value_type
表示迭代器所指元素的型别。 different_type
表示迭代器之间的距离的型别,在针对原生指针的特化版本用ptrdiff_t
表示,即:
template<typename T>struct iterator_traits<T*>{ typedef ptrdiff_t difference_type;}
reference_type & pointer
这两种类型都返回左值。
其中reference_type表示迭代器所指的对象的左值,而pointer表示迭代器所指对象的地址的左值。
前者对应操作符*
,后者对应操作符->
最后一个比较复杂的型别:iterator_category
迭代器被分为5类:
Input :只读
Output :只写
Forward :可读写
Bidirectional:可双向读写
Random Access:可以随机访问
这些迭代器存在一种功能上的汇总关系,如图
在代码里面则是用继承来实现
在设计算法时,如果可能尽量使用最合适的版本,也就是尽量找迭代器类型的最佳匹配。
书中以advance
函数为例,在stl_iterator_base.h
文件中定义,为了对比STL源码的版本,书中介绍了一种低效率的方式,即在代码中对迭代器类型进行判断,然后分别调用不同的函数,这样的方法直到运行的时候采取判断,如果再要提高效率,就只有在编译期就选择正确的版本。就需要使用函数重载了。
首先定义5中迭代器型别方便重载:
//继承关系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 {};
这里的继承关系就展示了上图中的迭代器分类的从属关系。
advance()
函数是外部接口,在内部都要加上前缀__advance()
,这就是真正的函数实现,通过迭代器型别进行重载。
//1.外部使用的接口template <class _InputIterator, class _Distance>inline void advance(_InputIterator& __i, _Distance __n) { __STL_REQUIRES(_InputIterator, _InputIterator); __advance(__i, __n, iterator_category(__i));}//__advance的重载版本,这里只有类型,没有临时变量(因为不必要)仅仅用来重载//重载 __advance input_iteratortemplate <class _InputIter, class _Distance>inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) { while (__n--) ++__i;}//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;}//RandomAccessIterator重载版本template <class _RandomAccessIterator, class _Distance>inline void __advance(_RandomAccessIterator& __i, _Distance __n, random_access_iterator_tag) { __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); __i += __n;}
那么问题来了,Forward版本的__advance
去哪了?
原来由于继承关系,当参数无法完全匹配时,会自动传递调用 Input的版本。
最后一个问题:STL是怎么判定迭代器型别的?也就是是如何实现iterator_category(__i)
?
首先先看:
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;};//原生指针的特化版本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;};//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;};
上述是iterator_traits的定义,包含了之前提到的所有5个型别,并有原生指针和const指针两个特化版本,然后,STL源码中写了如下函数:
template <class _Iter>inline typename iterator_traits<_Iter>::iterator_category//一整行作为函数返回类型__iterator_category(const _Iter&){ typedef typename iterator_traits<_Iter>::iterator_category _Category; return _Category();//创建一个临时对象 例如int()创建一个临时的int对象。}//而我们真正使用的接口直接调用了上述函数template <class _Iter>inline typename iterator_traits<_Iter>::iterator_categoryiterator_category(const _Iter& __i) { return __iterator_category(__i); }
- STL笔记(7)——Traits编程技法(二)
- STL学习笔记(traits编程技法)
- 《STL源码剖析》——迭代器(iterators)概念与traits编程技法(二)
- STL笔记(6)——Traits编程技法(一)
- STL itertor概念和traits编程技法(二)
- stl源码剖析学习笔记(二)traits编程技法简明例程
- 《STL源码剖析》——迭代器(iterators)概念与traits编程技法(一)
- Traits编程技法——STL源代码门钥
- STL源码剖析——type traits编程技法
- STL itertor概念和traits编程技法(一)
- C++—Traits编程技法
- STL之traits编程技法
- STL之traits编程技法
- STL中的traits编程技法
- STL中traits编程技法
- SGI STL学习笔记(2):traits编程技法
- C++——Traits编程技法
- C++ traits编程技法(一)
- MFC OnIdle函数学习
- 有关指针的数据类型和指针运算小结
- 《常见算法和数据结构》元素排序(2)——希尔排序(动画)
- c++实验3-个人所得税计算器
- OC_数据库常见SQL语句
- STL笔记(7)——Traits编程技法(二)
- 备份恢复类 面试题
- 14.Java IO: RandomAccessFile
- 【计算几何入门】poj 1269
- HashSet与HashMap底层实现
- svn插件下载与eclipse集成
- Spring之JMS之接受消息
- 多点定位方法的讨论
- 如何自定View