iterator
iterator
充当容器与算法之间的桥梁,使算法不需要了解具体的算法底层实现即能操作容器中的元素。迭代器可以理解为智能指针,原生指针(native pointer
)也是迭代器的一种。
stl_iterator_base.h
这个文件定义了迭代器的类型,以及针对不同类型迭代器的associated types
。(所回答的问题)
iterator_category
迭代器一共有五种类型(iterator_category
)
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
为例:
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
相关回答函数
struct output_iterator {
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
};
//比起其他类型,无_Distance>&参数
inline output_iterator_tag iterator_category(const output_iterator&)
{ return output_iterator_tag(); }
//output_iterator_tag 无 value_type
//output_iterator_tag 无 distance_type
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
template <class _InputIterator, class _Distance>
inline void advance(_InputIterator& __i, _Distance __n) {
__STL_REQUIRES(_InputIterator, _InputIterator);
__advance(__i, __n, iterator_category(__i));
}//总体调用这个函数
//根据iterator_category 的差异 定义不同类型迭代器的行为
//类似于 vector中的迭代器 支持跳跃,直接移动相应的距离
template <class _RandomAccessIterator, class _Distance>
inline void __advance(_RandomAccessIterator& __i, _Distance __n,
random_access_iterator_tag) {
__STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
__i += __n; // 双向,跳跃前进,加上标记 random_access_iterator_tag
}
//类似于slist、stack、queue中的迭代器,仅能单向单步移动
template <class _InputIter, class _Distance>
inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {
while (__n--) ++__i; // 单向,加上标记 input_iterator_tag
}
//类似于list、deque中的迭代器,支持双向 单步移动
template <class _BidirectionalIterator, class _Distance>
inline void __advance(_BidirectionalIterator& __i, _Distance __n,
bidirectional_iterator_tag) {
__STL_REQUIRES(_BidirectionalIterator, _BidirectionalIterator);
if (__n >= 0) // 双向,加上标记 bidirectional_iterator_tag
while (__n--) ++__i;
else
while (__n++) --__i;
}
distance
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));
}//总体调用这个函数
//根据iterator_category 的差异 定义不同类型迭代器的行为
//vector中的 随机访问迭代器 可以直接通过迭代器相减计算距离
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
前文说原生指针也是一种迭代器,故在此对其也进行了相应的回答
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
该迭代器用于支撑用户自定义的迭代器相应规则的答案。
#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 /* __STL_USE_NAMESPACES */
traits机制
通过萃取机制,使得使用更加灵活。
iterator_traits
负责萃取迭代器的特性,__type_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;
};
// native_pointer
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;
};
// native_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;
};
以下是通过萃取机去询问相应问题
iterator_category
获取迭代器类型
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
获取迭代器间距离
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
获取值类型
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
// class 没有任何成员,不会带来额外负担,却又能够标示真假。
struct __true_type {
};
struct __false_type {
};
基础traits定义
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; // Plain Old Data 是普通旧数据
};
//默认均为false类型
除了默认外,对传统数据类型进行了重载,进行重载的类型有:
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
使标准算法可以将结果存储在未初始化的内存中。其相关基础定义如下
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已移出
基础结构
进行封装后的原生指针。
template <class _Tp> class auto_ptr {
private:
_Tp* _M_ptr;
public:
typedef _Tp element_type;
}
构造函数
explicit
关键字用于防止隐式类型转换。
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
修饰外,即正常实现,不过多叙述
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()
函数,故其只适用于含有该函数的容器。
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;
}//调用底层容器的push_back
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
//基础iterator类型
template <class _Container>
inline output_iterator_tag
iterator_category(const back_insert_iterator<_Container>&)
{
return output_iterator_tag();
}
#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
//对外接口 传入的是支持push_back的容器 如 vector
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
该适配器允许在任意位置插入元素。故其底层比头插、尾插的类模板多一个迭代器用来调整插入位置。
template <class _Container>
class insert_iterator {
protected:
_Container* container;
typename _Container::iterator iter;
};
同样的,对外接口inserter
除了要传容器外,还需要传一个迭代器(指明插入位置)
reverse_bidirectional_iterator
双向翻转迭代器,可双向访问。++ --
和实际恰好相反。*iter
原本返回的是左侧元素,现在也随之翻转,返回右侧。由于是bidirectional_iterator_tag
的翻转版,仅支持单步移动(类似于list)
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;
}//正常end()的返回形式,不过--已重载
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
_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;
}
};
//迭代器类型 bidirectional_iterator_tag
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();
}
//value_type
template <class _BidirectionalIterator, class _Tp, class _Reference, class _Distance>
inline _Tp* value_type(const reverse_bidirectional_iterator
<_BidirectionalIterator, _Tp,_Reference, _Distance>&)
{
return (_Tp*) 0;
}
//distance_type
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();
}
//同理 还重载了!= 返回为 !(x==y)
reverse_iterator
同样,是双向均翻转的迭代器。
与reverse_bidirectional_iterator
不同的是其翻转的是random_access_iterator_tag
,故支持移动多个位置及随机访问。
_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
对象上,使之具备输入能力。
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*()); }
};
//迭代器类型 input_iterator_tag
template <class _Tp, class _Dist>
inline input_iterator_tag iterator_category(const istream_iterator<_Tp, _Dist>&)
{
return input_iterator_tag();
}
ostream_iterator
将迭代器绑定到一个 ostream
对象上,使之具备输出能力。
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>>
会忽略空格
。因此考虑直接在缓冲区中读取。
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:
//赋值及*iter
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(); //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
同理,将数据流出至缓冲区。无++
运算符(返回自身)
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;
};