迭代器的分类
定义在 <stl_iterator_base.h> 五种迭代器类型:
- 输入迭代器 (input_iterator):只读,且只能一次读操作,支持操作:++p,p++,!=,==,=*p,p->。
- 输出迭代器 (output_iterator):只写,且只能一次写操作,支持操作:++p,p++。
- 正向迭代器 (forward_iterator):可多次读写,支持输入输出迭代器的所有操作。
- 双向迭代器 (bidirectional_iterator):支持正向迭代器的所有操作,且支持操作:--p,p--。
- 随机访问迭代器 (random_access_iterator):除了支持双向迭代器操作外,还支持:p[n],p+n,n+p,p-n,p+=n,p-=n,p1-p2,p1<p2,p1>p2,p1>=p2,p1<=p2。
//@ 迭代器类型标签
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 {};
/*以下是五种迭代器类型数据类型*/
template <class _Tp, class _Distance> struct input_iterator {
typedef input_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
};
struct output_iterator {
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;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
};
template <class _Tp, class _Distance> struct bidirectional_iterator {
typedef bidirectional_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
};
template <class _Tp, class _Distance> struct random_access_iterator {
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
};
如果要自行开发迭代器最好继承自 std::iterator:
//@ 用户自己的写的迭代器最好继承此 std::iterator
#ifdef __STL_USE_NAMESPACES
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;
};
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; //@ 被迭代类型的引用类型
};
原生指针的特化:
template <class _Tp>
struct iterator_traits<_Tp*> {
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type; //@ C++ 内建的 ptrdiff_t 类型
typedef _Tp* pointer;
typedef _Tp& reference;
};
pointer to 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;
};
所以为了提高效率,使用迭代器类型最匹配的算法函数去调用:
- 首先通过traits技术获得迭代器类型iterator_category。
- 在函数调用时生成相应迭代器类型的临时对象作为实参传递,编译器就会调用相应的重载函数。
为了重载函数识别,SGI 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
//@ 函数重载,使迭代器能在编译时期就确定调用哪个函数
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));
}
__type_traits
但是在 STL 中,Traits技术只是用来规范迭代器,对于迭代器之外的东西没有加以规范。因此,SGI 将该技术扩展到迭代器之外的东西,称为 __type_traits
。iterator_traits是萃取迭代器的特性,而 __type_traits
是萃取型别的特性。
定义在 <type_traits.h> 萃取的型别如下:
- 是否具备 non-trivial default ctor ?
- 是否具备 non-trivial copy ctor ?
- 是否具备 non-trivial assignment operator ?
- 是否具备 non-trivial dtor ?
- 是否为 POD型别 ?
其中 non-trivial 意指非默认的相应函数,编译器会为每个类构造以上四种默认的函数,如果没有定义自己的,就会用编译器默认函数,如果使用默认的函数,我们可以使用 memcpy(),memmove(),malloc() 等函数来加快速度,提高效率。
//@ trivial
template <class _Tp>
struct __type_traits {
//@ 不要移除这个成员,它将通知编译器所看到的 __type__traits template 是特殊的
typedef __true_type this_dummy_member_must_be_first;
//@ 可以重排以下成员的次序
//@ 可以移除下列任何一个成员
//@ 不可以只重命名下列成员而没有改变编译器中对应的名称
//@ 新加入的成员会被视为一般成员,除非在编译器中加入相应的支持
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 is_POD_type;
};
其中返回真假的对象是:
struct __true_type {
};
struct __false_type {
};
将 bool,char,short,int,long,float,double 等基本的数据类型及其相应的指针类型的这些特性都定义为 __true_type
,这意味着,这些对基本类型进行构造、析构、拷贝、赋值等操作时,都是使用系统函数进行的。除了这些类型之外的其他类型,除非用户指定了它的这些特性为 __true_type
,默认都是 __false_type
的,不能直接调用系统函数来进行内存配置或赋值等,而需要调用该类型的构造函数、拷贝构造函数等。
#ifndef __STL_NO_BOOL
__STL_TEMPLATE_NULL struct __type_traits<bool> {
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;
};
#endif /* __STL_NO_BOOL */
__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;
};
__STL_TEMPLATE_NULL struct __type_traits<signed 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;
};
__STL_TEMPLATE_NULL struct __type_traits<unsigned 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;
};
#ifdef __STL_HAS_WCHAR_T
__STL_TEMPLATE_NULL struct __type_traits<wchar_t> {
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;
};
#endif /* __STL_HAS_WCHAR_T */
__STL_TEMPLATE_NULL struct __type_traits<short> {
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;
};
__STL_TEMPLATE_NULL struct __type_traits<unsigned short> {
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;
};
__STL_TEMPLATE_NULL struct __type_traits<int> {
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;
};
__STL_TEMPLATE_NULL struct __type_traits<unsigned int> {
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;
};
__STL_TEMPLATE_NULL struct __type_traits<long> {
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;
};
__STL_TEMPLATE_NULL struct __type_traits<unsigned long> {
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;
};
#ifdef __STL_LONG_LONG
__STL_TEMPLATE_NULL struct __type_traits<long long> {
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;
};
__STL_TEMPLATE_NULL struct __type_traits<unsigned long long> {
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;
};
#endif /* __STL_LONG_LONG */
__STL_TEMPLATE_NULL struct __type_traits<float> {
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;
};
__STL_TEMPLATE_NULL struct __type_traits<double> {
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;
};
__STL_TEMPLATE_NULL struct __type_traits<long double> {
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 __type_traits<_Tp*> {
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;
};
总结
- 迭代器分为五种类型:input_iterator,output_iterator,forward_iterator,bidirectional_iterator,random_access_iterator。
- iterator_traits 包含五大元素:iterator_category ,value_type,difference_type,pointer,reference。
- iterator_traits 是萃取迭代器的特性,而 __type_traits 是萃取型别的特性。