此系列是本人阅读《STL源码剖析》的一点心得体会,并结合部分STL源码加深理解。此篇博客为第三章iterator的读书笔记。
综述
有个地方容易混淆,首先,有五种iiterator
- input iterator
- output iterator
- forward iterator,
- bidirectional iterator,
- random-access iterator
但是又有
- insert iterator
- stream iterator
- reverse iterator
move iterator
那么到底是怎么分类的?
《C++标准库》有一句话说的很好,“iterator是一个抽象概念,任何东西,只要其行为像iterator,它就是iterator”。而不同的容器可能需要不同行进能力的iterator。input iterator, output iterator, forward iterator, bidirectional iterator, random-access iterator就是以行进能力来区分iterator,称之为iterator category。
而insert iterator, stream iterator, reverse iterator, move iterator属于迭代器适配器(iterator adpater),是C++库提供的预定义的特殊迭代器,可以说是对迭代器功能性的补足吧。
iterator_category
iterator模板有五个型别(type)
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;
};
区分不同category的iterator主要依靠其型别(type) iterator_category,不同的iterator将不同的struct定义为其iterator_category,以利用模板参数推导,使得类模板或函数模板针对不同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 {};
可以看到,除了output iterator外,不同的struct是依次继承的关系。那么这样设计有什么好处呢?可以利用继承机制来简化代码。
书中99页的例子对此做出了解释。distance()函数可以计算两个迭代器之间的距离,对于input iterator, forward iterator, bidirectional iterator, 只能一次次移动迭代器进行计算,而对于ra