1.1 STL迭代器
1.1.1 STL迭代器的作用
迭代器是STL库实现的一个规范,巧妙的利用数学上的 [ ) 符号,即闭区间、开区间,来表示容器所拥有的元素。
用户使用迭代器访问容器的元素的时候,简单、易用,可以避免许多错误。
代码也会显的紧凑、简洁、美观。
迭代器作为STL容器和算法的粘合剂,实现了数据结构和算法的分离。
STL库通过迭代器给用户提供访问接口,可以隐藏去多内部实现细节。
满足了封装性的设计要求。
只要用户遵守STL规范,就可以在已有STL组件的基础上扩展自定义的组件,并且这种扩展是比较简单容易的。
通过上面两点可以看出,迭代器的提供,使得STL库的设计满足“开闭原则”的,满足“封装性”原则的。
1.1.2 STL迭代器的相应型别
STL迭代器的相应型别,最常用的包含下面五种。
1.1.2.1 STL迭代器所指对象的型别-value_type
STL所指对象的型别,是指STL容器内所存储的数据类型。比如:
std::map<int> stu_id;
std::map<int>::iterator stu_id_iter;
那这里的 stu_id_iter所指对象的型别是int。
在STL规范中,任何一个迭代器都要提供一个value_type成员型别,这样我们就可以通过强大的stl迭代器萃取剂获取迭代器相应型别。
例如,通过下面的方法就可以获取value_type
iterator_traits<stu_id_iter>::value_type
1.1.2.2 STL迭代器所指对象的引用型别-reference
每一个STL迭代器都有一个 reference 型别,其实它的定义如下,
typedef value_type& reference
1.1.2.3 STL迭代器所指对象的指针型别-pointer
每一个STL迭代器都有一个pointer 型别,它的定义如下,
typedef value_type* pointer
1.1.2.4 STL迭代器的距离型别-difference_type
每一个STL迭代器都有一个 difference_type ,它的定义如下,
typedef ptrdiff_t difference_type;
这个特性主要是用来计算两个迭代器之间的距离,例如:
std::map<int> stu_id;
std::map<int>::iterator stu_id_iter_begin = stu_id.begin();
std::map<int>::iterator stu_id_iter_end = stu_id.end();
iterator_traits<stu_id_iter_begin>::difference_type distance;
distance = stu_id_iter_end – stu_id_iter_begin;
这个特性对于我们遍历“随机迭代器”所指向的元素时,很有用,我们可以通过计算出两个迭代器的距离,得出所包含的元素个数,这样就可以省去迭代器本身的构造、析构的开销。(不知道你理解我这段话的意思没?^_^)
1.1.2.5 STL迭代器的种类型别-iterator_category
STL中迭代器目前被分为五种类型:
Input Iterator:这种迭代器所指对象,不允许外界改变。只读。
Output Iterator:只写。
Forward Iterator:允许“写入型”算法(例如replace())在此种迭代器所形成的区间上进行读写操作。
Bidirectional Iterator:可双向移动。
Random Access Iterator:前四种迭代器都只供应一部分指针算术能力(前三种支持 operator++,第四种再加上 operator--),第五种则涵盖所有指针算术能力,包括 p+n, p-n, p[n], p1-p2, p1<p2。
Input Iterator Output Iterator
Forward Iterator
Bidirectional Iterator
Random Access Iterator |
//定义五种迭代器的类型
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{};
1.1.3 STL迭代器萃取剂-iterator_traits
上面讲了迭代器的五种相应型别,只要你告诉stl一个迭代器,它就能告诉你想要的五种型别,这个靠什么呢?靠的就是伟大的iterator_traits。我们看看具体的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 T>
struct iterator_traits<T *>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef ptrdiff_t difference_type;
};
//针对原生指向常量对象的指针的特化版本
template <class T>
struct iterator_traits<const T *>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef const T* pointer;
typedef const T& reference;
typedef ptrdiff_t difference_type;
};
看了代码是不是觉得没啥?很简单啊?我也是这个感觉。^_^
但是这种设计思想,那真是了不起哦,可以说是stl的主心骨了。实在是厉害。
疑问,这个 Input Iterator 和 Forward Iterator到底有什么区别呢?为什么要增加一个Forward Iterator?