迭代器是什么
迭代器是一种模式,实现了通过一个统一接口访问STL容器的方法。STL作为桥梁链接了STL算法与容器。例如,我们可以通过Sort(a.begin() , a.end())完成一次利用算法对vector类型容器a的排序。
迭代器的设计
标准STL中,迭代器在容器内部,每种容器都有自己专属的迭代器。这样做的原因是,如果要创建迭代器,就必须访问容器的内部结构,所以直接封装进容器内部是最简单的方式。
如何获得迭代器指向的数据类型
迭代器的设计过程中需要获得迭代器指向的数据类型,有效的一种方式是通过Traits来提取Value Type,对于原生指针,可以提取出指针指向的Value Type。如:
template<calss T>
struct Test<T*>{
typedef T value_type;
}
通过实现多个不同的Template 特化版本,就能实现多种数据类型的类型提取
迭代器的五种类型
- input iterator 只读
- output iterator 只写
- forward iterator 允许区间操作
- bidlrectional iterator 双向移动
- random access iterator 支持随机访问
迭代器内部常用的五种型别
- value type : 内部值的类型
- difference type : 表示迭代器之间的距离
- reference type : 内部数据的引用类型。代表着iter指向的内容是否是const的,如果不是const那么解引用应该返回引用(左值)而不是值(右值)
- pointer type : 内部数据的指针类型
- iterator_category : iterator的类型。需要根据不同类型做出不同响应
std::iterator
STL提供了一个iterator基类,自己实现的iterator只要继承此类就能够保证实现了五个型别
template<class T>
struct iterator_traits<T*>
{
typedef random_access_iterator_tag iterator_category; // 指针的category是random类型
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
//针对Pointer-to-const而设计的traits偏特化版本
template<class T>
struct iterator_traits<const T*>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T reference;
};
流程总结
//五种迭代器,作为tag供重载使用
struct input_iterator_tag{};
struct output_iteratoe_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{};
从模板中获得当前iterator属于哪个型别,获得型别后根据同一接口调用不同函数:
/*函数重载,使迭代器能在编译时期就确定调用哪个函数*/
template <class _InputIter, class _Distance>
/*迭代器类型为input_iterator_tag的函数定义*/
inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {
while (__n--) ++__i;
}
template <class _BidirectionalIterator, class _Distance>
/*迭代器类型为bidirectional_iterator_tag的函数定义*/
inline void __advance(_BidirectionalIterator& __i, _Distance __n,
bidirectional_iterator_tag) {
__STL_REQUIRES(_BidirectionalIterator, _BidirectionalIterator);
if (__n >= 0)
while (__n--) ++__i;
else
while (__n++) --__i;
}
template <class _RandomAccessIterator, class _Distance>
/*迭代器类型为random_access_iterator_tag的函数定义*/
inline void __advance(_RandomAccessIterator& __i, _Distance __n,
random_access_iterator_tag) {
__STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
__i += __n;
}
template <class _InputIterator, class _Distance>
/*决定调用哪个函数,这是一个对外接口*/
inline void advance(_InputIterator& __i, _Distance __n) {
__STL_REQUIRES(_InputIterator, _InputIterator);
__advance(__i, __n, iterator_category(__i));
}
SGI对traits进行扩展
iterator_traits负责萃取迭代器的特性,__type_traits负责萃取型别(type)的特性
- 是否具备non-trivial default ctor?
- 是否具备non-trivial copy ctor?
- 是否具备non-trivial assignment operator?
- 是否具备non-trivial dtor?
- 是否为POD(plain old data)型别?
通过指定类型,在编译期间决定以上特性 ,来避免额外调用(如construct , destruct等),提高效率
struct _true_type{};
struct _false_type{};
/*
*非基本数据类型,默认指定为_false_type只能自己初始化,不能系统进行
*/
template<class T>
struct _type_traits
{
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;
typedef _false_type has_POD_type;
};