STL 迭代器

15 篇文章 0 订阅
一、迭代器基类


下面的列表定义了迭代器的类型,类型通过使用一个空结构来描述,但是可以通过RTTI来获取迭代器的名称
// ITERATOR TAGS (from <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  {};
// TEMPLATE CLASS iterator (from <iterator>)


//迭代器的基类定义,这里只定义了几个类型定义


_C:  指定迭代器类型,这个参数用前面5种中的一个填充
_Ty: 迭代器的值的类型,即*操作得到的类型
_D:  两个迭代器相减的类型


template<class _C, class _Ty, class _D = ptrdiff_t>
struct iterator {
typedef _C iterator_category;
typedef _Ty value_type;
typedef _D distance_type;
};


这是双向迭代器的基类
_Ty: 参考上面
_D: 参考上面
template<class _Ty, class _D>
struct _Bidit : public iterator<bidirectional_iterator_tag,
_Ty, _D> {};


这是随机迭代器的类型的基类
template<class _Ty, class _D>
struct _Ranit : public iterator<random_access_iterator_tag,
_Ty, _D> {};
// TEMPLATE CLASS iterator_traits (from <iterator>)




//这是一个迭代器特性类,用来描述迭代器的特性
_It:  指定迭代器类
template<class _It>
struct iterator_traits {
typedef _It::iterator_category iterator_category;
typedef _It::value_type value_type;
typedef _It::distance_type distance_type;
};




具体的迭代器由容器实现,也就是具体的容器实现不同的迭代器,但关键是这些迭代器具有统一的操作接口.
对于容器来说,一般在容器类内实现迭代器,而这些迭代器则是从前面的介绍的类型中直接或者间接派生.




二、迭代器的5种类型


输入迭代器:


这种迭代器支持如下操作:


const value_type & operator *() const
const value_type*  operator ->() const
operator ++(), operator ++(int) 


支持operator==, operator !=操作


即只支持从容器中读取的功能,而不能写入,同时只支持向前迭代而不支持向后迭代。输入迭代器只支持一次读取。也就是说当将一个迭代器赋值给另外一个迭代器时。而两个迭代器进行向前迭代时,所得到的值将是不一样的(当然若进行赋值时而没有进行迭代则两者获得的值还是一样的)。两个迭代器相等与不等不是指他们所指的值相等而是迭代器所引用的容器是否相等。在STL中只实现了一种输入迭代器:


template <
   class Type 
   class CharType = char
   class Traits = char_traits<CharType>
   class Distance= ptrdiff_t
>
class istream_iterator : 
public iterator<input_iterator_tag, Type, Distance, const Type *, const Type &>


istream_iterator是专门为istream类服务的迭代器其中:


Type:  指定迭代器所读取的数值的类型
CharType, Traits: 是为istream准备的(作为basic_istream类的模板参数)
Distance: 默认的指定两个迭代器差的类型




输入迭代器的构造:


istream_iterator( );
istream_iterator(
   istream_type& _Istr   //这里指定一个输入流对象(如: cin),当使用这个构造时迭代器会要求提供一个输入
);


下面举例:要求输入N个数到一个数组中:






int *pArray;
int nCount;


cout <<"输入数组元素个数:";
istream_iterator<int> iter(cin);   //这里会要求输入
nCount = *iter;
pArray = new int[nCount];
for (int i = 0; i < nCount; i++)
 pArray[i] = * ++iter












输出迭代器:


这种迭代器只支持:


迭代器& operator = (value_type & ){}    //这个操作执行具体的写迭代器操作
迭代器& operator *()
迭代器& operator ++()
迭代器 operator++(int)


不支持 ==, !=进行比较


输入迭代器只支持向容器中写入数据,而且两次写入同一个地方,并不会覆盖原来的值,目前只有只实现了输出迭代器:ostream_iterator.


template<class _U, class _E = char,              //_U: 指定写入的类型
class _Tr = char_traits<_E> >
class ostream_iterator
: public iterator<output_iterator_tag, void, void> 


ostream_iterator的构造函数是要求一个输出流对象,而且构造函数并不会执行一个写入:




下面将一个数组内容输出:


int array[]{1,2,3,4};


ostream_iterator<int> iter(cout);


for(int i = 0; i < 4; i++)
{
*iter++ = array[i];
}




插入迭代器


插入迭代器也是一种输出迭代器,也就是只在操作符=实现了特定意义,而其他的* ++ ->等并不会使迭代器移动,也不会得到迭代所指的元素。(也就是说++不管如何都只返回迭代器本身而*也是迭代器本身)。这种迭代的作用只是为了输出。也就是说只有=才有意义。STL中定义了三中插入迭代器:




*****后查迭代器***************


//C:  指定容器的类型,这里的容器只要支持push_back函数就可以了: vector, list, deque, string


template<class _C>
class back_insert_iterator
: public iterator<output_iterator_tag, void, void> {
public:
typedef _C container_type;
typedef _C::value_type value_type;
explicit back_insert_iterator(_C& _X)
: container(_X) {}
back_insert_iterator<_C>& operator=(
const value_type& _V)
{container.push_back(_V);       //每执行一次赋值操作都是将参数插入容器的后面,所以叫后插迭代
return (*this); }
back_insert_iterator<_C>& operator*()
{return (*this); }
back_insert_iterator<_C>& operator++()
{return (*this); }
back_insert_iterator<_C> operator++(int)
{return (*this); }                   //这里可以看出输出迭代的++,-> *并不代表任何意义,但仍可以使用他们
protected:
_C& container;
};




构造一个后查迭代器可以调用函数:


template<class _C> inline
back_insert_iterator<_C> back_inserter(_C& _X)
{return (back_insert_iterator<_C>(_X)); }






*************前插迭代器*****


template<class _C>
class front_insert_iterator
: public iterator<output_iterator_tag, void, void> {
public:
typedef _C container_type;
typedef _C::value_type value_type;
explicit front_insert_iterator(_C& _X)
: container(_X) {}
front_insert_iterator<_C>& operator=(
const value_type& _V)
{container.push_front(_V);        //只要容器支持push_front都可以,只有list, deque才支持
return (*this); }
front_insert_iterator<_C>& operator*()
{return (*this); }
front_insert_iterator<_C>& operator++()
{return (*this); }
front_insert_iterator<_C> operator++(int)
{return (*this); }
protected:
_C& container;
};




构造一个前查迭代器可以调用函数:


template<class _C> inline
front_insert_iterator<_C> front_inserter(_C& _X)
{return (front_insert_iterator<_C>(_X)); }






***************插入器*****************
template<class _C>
class insert_iterator
: public iterator<output_iterator_tag, void, void> {
public:
typedef _C container_type;
typedef _C::value_type value_type;
insert_iterator(_C& _X, _C::iterator _I)
: container(_X), iter(_I) {}
insert_iterator<_C>& operator=(
const value_type& _V)
{iter = container.insert(iter, _V);   //只要实现了insert的容器都可以,vector, list, deque, set, map, string, multiset, multimap
++iter;
return (*this); }
insert_iterator<_C>& operator*()
{return (*this); }
insert_iterator<_C>& operator++()
{return (*this); }
insert_iterator<_C>& operator++(int)
{return (*this); }
protected:
_C& container;
_C::iterator iter;
};




构造一个插入器可以调用函数:


template<class _C, class _XI> inline
insert_iterator<_C> inserter(_C& _X, _XI _I)
{return (insert_iterator<_C>(_X, _C::iterator(_I))); }






在插入器中,构造函数中有两个一个是容器的引用,一个是迭代器,每次赋值后迭代器总会后移一个,因此插入器实现的是从开始传递的迭代开始,依次往后插入。,(但在set, map中却不是这样的.因为set, map中的insert的结果并不一定会放在迭代器之前)








*********************
插入迭代器是一个输出迭代器那他的作用有什么意义呢? 意义就在于迭代器可以动态增长,在所有带copy的算法中都要求接收元素的迭代器的范围必须足够大,否则将会产生异常。但实际中有时候并不知道需要多大的迭代器范围,所以我们需要在赋值时使目标动态的增长,这样我们只需要在带copy的算法中使用插入迭代器就满足了要求了。因为每次的赋值其实就是一次insert动作。下面例子能说明问题:




vector<int> v1, v2;
//系统对v1设置了很多的元素,现在要将元素拷贝给v2
back_insert_iterator<vector<int> > bi(v2);    //注意这里的构造
copy(v1.begin(), v1.end(), bi);     //这里每次赋值实际上都是执行了push_back操作














为了能够快速的获取三种迭代器,而不需要在去定义麻烦的内容,STL中实现了三个摸板函数,分别用来获得三个迭代器:


template<class _C> inline
back_insert_iterator<_C> back_inserter(_C& _X)             //back_inserter只需要将一个容器引用作为参数就将返回一个后插迭代器
{return (back_insert_iterator<_C>(_X)); }




template<class _C> inline
front_insert_iterator<_C> front_inserter(_C& _X)
{return (front_insert_iterator<_C>(_X)); }






template<class _C, class _XI> inline
insert_iterator<_C> inserter(_C& _X, _XI _I)                    //这里需要指定一个容器引用和其中的想插入之前的迭代器
{return (insert_iterator<_C>(_X, _C::iterator(_I))); }






前面的代码可以改成:


vector<int> v1, v2;
//系统对v1设置了很多的元素,现在要将元素拷贝给v2
copy(v1.begin(), v1.end(), back_inserter(v2));     //这里每次赋值实际上都是执行了push_back操作




















vector的迭代器是一个指针,而list的迭代器则只是一个对象。



















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值