本文是阅读SGI STL
源码中关于iterator
部分的笔记
同样,本文仍然是建立在已经观看过侯捷老师STL源码剖析课程的基础上。是在阅读源码过程中,对其中的内容进行补充、修饰。
另外SGI STL
源码中关于Adapter
部分没有严格的文件进行描述,在其出现的相应位置,对相关的类模板进行了改造(如:container adapter
中有 stack queue
,iterator adapter
中有istream_iterator
等)
iterator
iterator
充当容器与算法之间的桥梁,使算法不需要了解具体的算法底层实现即能操作容器中的元素。迭代器可以理解为智能指针,原生指针(native pointer
)也是迭代器的一种。
stl_iterator_base.h
这个文件定义了迭代器的类型,以及针对不同类型迭代器的associated types
。(所回答的问题)
iterator_category
迭代器一共有五种类型(iterator_category
)
1 2 3 4 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{};
|
associated type
迭代器所回答的问题,有iterator_category value_type difference_type pointer reference
五个
下面是针对五种基础类型的迭代器进行定义的问题答案:
以input_iterator_tag
为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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; }; template <class _Tp, class _Distance> inline input_iterator_tag iterator_category(const input_iterator<_Tp, _Distance>&) { return input_iterator_tag(); } template <class _Tp, class _Distance> inline _Tp* value_type(const input_iterator<_Tp, _Distance>&) { return (_Tp*)(0); } template <class _Tp, class _Distance> inline _Distance* distance_type(const input_iterator<_Tp, _Distance>&) { return (_Distance*)(0); }
|
关于value_type distance_type iterator_category
的回答方式,除output_iterator_tag
外其余几种类型的迭代器均一致,在此不再罗列。仅列出output_iterator_tag
相关回答函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| struct output_iterator { typedef output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference; };
inline output_iterator_tag iterator_category(const output_iterator&) { return output_iterator_tag(); }
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; };
|
advance/distance
迭代器的类型不同,其所能移动的方式也不同,进而在移动(advance)/距离(distance)实现的方式上也有着差距:
advance
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| template <class _InputIterator, class _Distance> inline void advance(_InputIterator& __i, _Distance __n) { __STL_REQUIRES(_InputIterator, _InputIterator); __advance(__i, __n, iterator_category(__i)); }
template <class _RandomAccessIterator, class _Distance> inline void __advance(_RandomAccessIterator& __i, _Distance __n, random_access_iterator_tag) { __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); __i += __n; }
template <class _InputIter, class _Distance> inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) { while (__n--) ++__i; }
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; }
|
distance
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| template <class _InputIterator, class _Distance> inline void distance(_InputIterator __first, _InputIterator __last, _Distance& __n) { __STL_REQUIRES(_InputIterator, _InputIterator); __distance(__first, __last, __n, iterator_category(__first)); }
template <class _RandomAccessIterator, class _Distance> inline void __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, _Distance& __n, random_access_iterator_tag) { __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator); __n += __last - __first; }
template <class _InputIterator, class _Distance> inline void __distance(_InputIterator __first, _InputIterator __last, _Distance& __n, input_iterator_tag) { while (__first != __last) { ++__first; ++__n; } }
|
native pointer
前文说原生指针也是一种迭代器,故在此对其也进行了相应的回答
1 2 3 4 5 6 7
| template <class _Tp> inline random_access_iterator_tag iterator_category(const _Tp*) { return random_access_iterator_tag(); } template <class _Tp> inline _Tp* value_type(const _Tp*) { return (_Tp*)(0); } template <class _Tp> inline ptrdiff_t* distance_type(const _Tp*) { return (ptrdiff_t*)(0); }
|
std::iterator
除了默认的五种类型的迭代器外,还规定了另外一种std::iterator
该迭代器用于支撑用户自定义的迭代器相应规则的答案。
1 2 3 4 5 6 7 8 9 10 11 12
| #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; }; #endif
|
traits机制
通过萃取机制,使得使用更加灵活。
iterator_traits
负责萃取迭代器的特性,__type_traits
负责萃取类型的特性。
iterator_traits
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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; };
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_category
获取迭代器类型
1 2 3 4 5 6 7 8 9 10 11
| template <class _Iter> inline typename iterator_traits<_Iter>::iterator_category __iterator_category(const _Iter&) { typedef typename iterator_traits<_Iter>::iterator_category _Category; return _Category(); } template <class _Iter> inline typename iterator_traits<_Iter>::iterator_category iterator_category(const _Iter& __i) { return __iterator_category(__i); }
|
difference_type
获取迭代器间距离
1 2 3 4 5 6 7 8 9
| template <class _Iter> inline typename iterator_traits<_Iter>::difference_type* __distance_type(const _Iter&) { return static_cast<typename iterator_traits<_Iter>::difference_type*>(0); } template <class _Iter> inline typename iterator_traits<_Iter>::difference_type* distance_type(const _Iter& __i) { return __distance_type(__i); }
|
value_type
获取值类型
1 2 3 4 5 6 7 8 9
| template <class _Iter> inline typename iterator_traits<_Iter>::value_type* __value_type(const _Iter&) { return static_cast<typename iterator_traits<_Iter>::value_type*>(0); } template <class _Iter> inline typename iterator_traits<_Iter>::value_type* value_type(const _Iter& __i) { return __value_type(__i); }
|
__type_traits
提供了一种机制,允许针对不同的类型属性,在编译时期完成函数派送(function dispatch)
true/false
1 2 3 4 5 6
| struct __true_type { };
struct __false_type { };
|
基础traits定义
1 2 3 4 5 6 7 8 9 10
| template <class _Tp> struct __type_traits { 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; };
|
除了默认外,对传统数据类型进行了重载,进行重载的类型有:
bool
、 char
、signed char
、unsigned char
、wchar_t
、short
、unsigned short
、int
、unsigned int
、long
、unsigned long
、long long
、unsigned long long
、float
、double
、long double
、char*
、signed char*
、unsigned char*
、const char*
、const signed char*
、const unsigned char*
、template <class _Tp> _Tp*
以上类型默认__type_traits
各成员均为true
除此之外,关于数组大小的限制,要求是int
型,故也有_Is_integer
类型萃取。
bool
、 char
、signed char
、unsigned char
、wchar_t
、short
、unsigned short
、int
、unsigned int
、long
、unsigned long
、long long
、unsigned long long
raw_storage_iterator
使标准算法可以将结果存储在未初始化的内存中。其相关基础定义如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| template <class _ForwardIterator, class _Tp> class raw_storage_iterator { protected: _ForwardIterator _M_iter; public: typedef output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference;
explicit raw_storage_iterator(_ForwardIterator __x) : _M_iter(__x) {} raw_storage_iterator& operator*() { return *this; } raw_storage_iterator& operator=(const _Tp& __element) { construct(&*_M_iter, __element); return *this; } raw_storage_iterator<_ForwardIterator, _Tp>& operator++() { ++_M_iter; return *this; } raw_storage_iterator<_ForwardIterator, _Tp> operator++(int) { raw_storage_iterator<_ForwardIterator, _Tp> __tmp = *this; ++_M_iter; return __tmp; } }; template <class _ForwardIterator, class _Tp> inline output_iterator_tag iterator_category(const raw_storage_iterator<_ForwardIterator, _Tp>&) { return output_iterator_tag(); }
|
auto_ptr
前面说道 迭代器可以理解为智能指针,这里将介绍一下智能指针。
auto_ptr
在c++11弃用,在c++17已移出
基础结构
进行封装后的原生指针。
1 2 3 4 5 6 7
| template <class _Tp> class auto_ptr { private: _Tp* _M_ptr;
public: typedef _Tp element_type; }
|
构造函数
explicit
关键字用于防止隐式类型转换。
1 2 3 4 5 6 7 8 9
| explicit auto_ptr(_Tp* __p = 0) __STL_NOTHROW : _M_ptr(__p) {} auto_ptr(auto_ptr& __a) __STL_NOTHROW : _M_ptr(__a.release()) {} template <class _Tp1> auto_ptr(auto_ptr<_Tp1>& __a) __STL_NOTHROW : _M_ptr(__a.release()) {}
_Tp* release() __STL_NOTHROW { _Tp* __tmp = _M_ptr; _M_ptr = 0; return __tmp; }
|
拷贝赋值
后续实现的功能除有__STL_NOTHROW
修饰外,即正常实现,不过多叙述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| auto_ptr& operator=(auto_ptr& __a) __STL_NOTHROW { if (&__a != this) { delete _M_ptr; _M_ptr = __a.release(); } return *this; }
template <class _Tp1> auto_ptr& operator=(auto_ptr<_Tp1>& __a) __STL_NOTHROW { if (__a.get() != this->get()) { delete _M_ptr; _M_ptr = __a.release(); } return *this; } _Tp* get() const __STL_NOTHROW { return _M_ptr; }
|
iterator adapter
back_insert_iterator
用于在指定容器的末尾处添加新元素。它的唯一数据成员是指向容器的指针,不指向容器内的任何元素,故++
操作对其没有意义。由于它会调用底层容器的push_back()
函数,故其只适用于含有该函数的容器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| template <class _Container> class back_insert_iterator { protected: _Container* container; public: typedef _Container container_type; typedef output_iterator_tag iterator_category; typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference;
explicit back_insert_iterator(_Container& __x) : container(&__x) {} back_insert_iterator<_Container>& operator=(const typename _Container::value_type& __value) { container->push_back(__value); return *this; } back_insert_iterator<_Container>& operator*() { return *this; } back_insert_iterator<_Container>& operator++() { return *this; } back_insert_iterator<_Container>& operator++(int) { return *this; }
};
#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
template <class _Container> inline output_iterator_tag iterator_category(const back_insert_iterator<_Container>&) { return output_iterator_tag(); }
#endif
template <class _Container> inline back_insert_iterator<_Container> back_inserter(_Container& __x) { return back_insert_iterator<_Container>(__x); }
|
front_insert_iterator
除了只能调用push_front()
函数与back_insert_iterator
完全一致。也提供对外接口front_inserter
insert_iterator
该适配器允许在任意位置插入元素。故其底层比头插、尾插的类模板多一个迭代器用来调整插入位置。
1 2 3 4 5 6
| template <class _Container> class insert_iterator { protected: _Container* container; typename _Container::iterator iter; };
|
同样的,对外接口inserter
除了要传容器外,还需要传一个迭代器(指明插入位置)
reverse_bidirectional_iterator
双向翻转迭代器,可双向访问。++ --
和实际恰好相反。*iter
原本返回的是左侧元素,现在也随之翻转,返回右侧。由于是bidirectional_iterator_tag
的翻转版,仅支持单步移动(类似于list)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| class reverse_bidirectional_iterator { typedef reverse_bidirectional_iterator <_BidirectionalIterator, _Tp, _Reference, _Distance> _Self; protected: _BidirectionalIterator current; public: typedef bidirectional_iterator_tag iterator_category; typedef _Tp value_type; typedef _Distance difference_type; typedef _Tp* pointer; typedef _Reference reference;
reverse_bidirectional_iterator() {} explicit reverse_bidirectional_iterator(_BidirectionalIterator __x) : current(__x) {} _BidirectionalIterator base() const { return current; } _Reference operator*() const { _BidirectionalIterator __tmp = current; return *--__tmp; } #ifndef __SGI_STL_NO_ARROW_OPERATOR pointer operator->() const { return &(operator*()); } #endif _Self& operator++() { --current; return *this; } _Self operator++(int) { _Self __tmp = *this; --current; return __tmp; } _Self& operator--() { ++current; return *this; } _Self operator--(int) { _Self __tmp = *this; ++current; return __tmp; } };
template <class _BidirectionalIterator, class _Tp, class _Reference, class _Distance> inline bidirectional_iterator_tag iterator_category(const reverse_bidirectional_iterator <_BidirectionalIterator, _Tp, _Reference, _Distance>&) { return bidirectional_iterator_tag(); }
template <class _BidirectionalIterator, class _Tp, class _Reference, class _Distance> inline _Tp* value_type(const reverse_bidirectional_iterator <_BidirectionalIterator, _Tp,_Reference, _Distance>&) { return (_Tp*) 0; }
template <class _BidirectionalIterator, class _Tp, class _Reference, class _Distance> inline _Distance* distance_type(const reverse_bidirectional_iterator <_BidirectionalIterator, _Tp,_Reference, _Distance>&) { return (_Distance*) 0; }
template <class _BiIter, class _Tp, class _Ref, class _Distance> inline bool operator==( const reverse_bidirectional_iterator<_BiIter, _Tp, _Ref, _Distance>& __x, const reverse_bidirectional_iterator<_BiIter, _Tp, _Ref, _Distance>& __y) { return __x.base() == __y.base(); }
|
reverse_iterator
同样,是双向均翻转的迭代器。
与reverse_bidirectional_iterator
不同的是其翻转的是random_access_iterator_tag
,故支持移动多个位置及随机访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| _Self operator+(_Distance __n) const { return _Self(current - __n); } _Self& operator+=(_Distance __n) { current -= __n; return *this; } _Self operator-(_Distance __n) const { return _Self(current + __n); } _Self& operator-=(_Distance __n) { current += __n; return *this; } _Reference operator[](_Distance __n) const { return *(*this + __n); }
|
istream_iterator
将迭代器绑定到一个 istream
对象上,使之具备输入能力。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| template <class _Tp, class _Dist> class istream_iterator { protected: istream* _M_stream; _Tp _M_value; bool _M_end_marker; void _M_read() { _M_end_marker = (*_M_stream) ? true : false; if (_M_end_marker) *_M_stream >> _M_value; _M_end_marker = (*_M_stream) ? true : false; } public: istream_iterator() : _M_stream(&cin), _M_end_marker(false) {} istream_iterator(istream& __s) : _M_stream(&__s) { _M_read(); } reference operator*() const { return _M_value; } pointer operator->() const { return &(operator*()); } };
template <class _Tp, class _Dist> inline input_iterator_tag iterator_category(const istream_iterator<_Tp, _Dist>&) { return input_iterator_tag(); }
|
ostream_iterator
将迭代器绑定到一个 ostream
对象上,使之具备输出能力。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| template <class _Tp> class ostream_iterator { protected: ostream* _M_stream; const char* _M_string; public: ostream_iterator(ostream& __s) : _M_stream(&__s), _M_string(0) {} ostream_iterator(ostream& __s, const char* __c) : _M_stream(&__s), _M_string(__c) {} ostream_iterator<_Tp>& operator=(const _Tp& __value) { *_M_stream << __value; if (_M_string) *_M_stream << _M_string; return *this; } };
|
istreambuf_iterator
由于isteam_iterator
采用operator>>
来读取,而operator>>
会忽略空格
。因此考虑直接在缓冲区中读取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| template<class _CharT, class _Traits> class istreambuf_iterator : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type, _CharT*, _CharT&> { public: typedef _CharT char_type; typedef _Traits traits_type; typedef typename _Traits::int_type int_type; typedef basic_streambuf<_CharT, _Traits> streambuf_type; typedef basic_istream<_CharT, _Traits> istream_type;
public: istreambuf_iterator(streambuf_type* __p = 0) { this->_M_init(__p); } istreambuf_iterator(istream_type& __is) { this->_M_init(__is.rdbuf()); } char_type operator*() const { return _M_is_initialized ? _M_c : _M_dereference_aux(); } private: streambuf_type* _M_buf; mutable _CharT _M_c; mutable bool _M_eof : 1; mutable bool _M_is_initialized : 1; };
template<class _CharT, class _Traits> _CharT istreambuf_iterator<_CharT, _Traits>::_M_dereference_aux() const { this->_M_getc(); return _M_c; }
istreambuf_iterator& operator++() { this->_M_nextc(); return *this; } istreambuf_iterator operator++(int) { if (!_M_is_initialized) _M_postincr_aux(); istreambuf_iterator __tmp = *this; this->_M_nextc(); return __tmp; } void _M_nextc() { int_type __c = _M_buf->snextc(); _M_c = traits_type::to_char_type(__c); _M_eof = traits_type::eq_int_type(__c, traits_type::eof()); _M_is_initialized = true; }
|
mutable关键字
在const
函数中,原则上不能够修改任意变量值。而如果变量是mutable
关键字修饰时,则可以在const
函数中进行修改。
mutable只能够用于一个类的非静态数据成员
ostreambuf_iterator
同理,将数据流出至缓冲区。无++
运算符(返回自身)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| template<class _CharT, class _Traits> class ostreambuf_iterator : public iterator<output_iterator_tag, void, void, void, void> { public: typedef _CharT char_type; typedef _Traits traits_type; typedef typename _Traits::int_type int_type; typedef basic_streambuf<_CharT, _Traits> streambuf_type; typedef basic_ostream<_CharT, _Traits> ostream_type;
public: ostreambuf_iterator(streambuf_type* __buf) : _M_buf(__buf), _M_ok(__buf) {} ostreambuf_iterator(ostream_type& __o) : _M_buf(__o.rdbuf()), _M_ok(__o.rdbuf() != 0) {}
ostreambuf_iterator& operator=(char_type __c) { _M_ok = _M_ok && !traits_type::eq_int_type(_M_buf->sputc(__c), traits_type::eof()); return *this; } ostreambuf_iterator& operator*() { return *this; } ostreambuf_iterator& operator++() { return *this; } ostreambuf_iterator& operator++(int) { return *this; }
bool failed() const { return !_M_ok; }
private: streambuf_type* _M_buf; bool _M_ok; };
|