STL 迭代器适配器(iterator adapter)
iterator adapter
iterator --- reverse_iterator
iterator --- Insert_iterator
iterator --- iostream_iterator
Insert_iterator --- back_insert_iterator
Insert_iterator --- front_insert_iterator
Insert_iterator --- insert_iterator
插入迭代器:将一般迭代器的赋值操作转变为插入操作。
insert iterator
当用户对inserter iterator作赋值操作时,就在inserter iterator类中定义的operator()中调用底层容器的插入操作(push_back,push_front,insert,etc.).
以back_inserter插入迭代适配器为例:(front_inserter和inserter与该类相类似)
template <class _Container>
inline back_insert_iterator<_Container> back_inserter(_Container& __x) {
return back_insert_iterator<_Container>(__x);
}
当用户调用back_inserter函数时,函数实际返回后向插入迭代器类(back_insert_iterator)对象,并将容器参数传递给后向插入迭代器类的构造函数。
后向插入迭代器类代码(back_insert_iterator):
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; }
};
类中有容器类指针_Container* container,指向待插入的容器。在类中定义的赋值操作符=中,调用了底层容器的push_back函数,将operator=参数__value插入到容器尾部。
类中还重载了迭代器操作符:dereference [],prefix_increment[++],post_increment[++(int)]。在其函数体中只是简单地返回当前迭代器本身(this),并未进行相应的前进等操作,说明对此类back_insert_iterator对象进行上述操作是不会产生什么效果。
结合例子分析:
#include<iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
int main(){
int ia[]={1,5,3,6,4,8,9};
vector<int> ivec(ia,ia+7);
ostream_iterator<int> outite(cout," ");
copy(ia,ia+3,back_inserter(ivec)); //a
copy(ivec.begin(),ivec.end(),outite);
//1 5 3 6 4 8 9 1 5 3
cout<<endl;
return 0;
}
程序中a行调用back_inserter函数,生成对ivec向量的后向迭代器对象(back_insert_iterator object),并将该对象传入到copy算法。在copy算法中将利用该对象作为函数,对容器中的对象进行处理。
在程序中,后向迭代器对象只是被当作一个函数(functor)使用,对容器调用该对象提供的功能,而不是像传统的迭代器来访问数组中的元素,因此,对其进行dereference [*],prefix_increment[++],post_increment[++(int)]操作都不会产生什么效果。
程序的运行结果为:
1 5 3 6 4 8 9 1 5 3
reverse iterator
反向迭代器:将迭代器的移动方向倒转:前进变为后退,后退变为前进。
在某些容器类中定义反向迭代器成员,如vector:
template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
class vector : protected _Vector_base<_Tp, _Alloc>
{
//...
typedef value_type* iterator; // vector的迭代器是普通指针
typedef const value_type* const_iterator;
typedef reverse_iterator<const_iterator> const_reverse_iterator;
typedef reverse_iterator<iterator> reverse_iterator;
reverse_iterator rbegin()
{ return reverse_iterator(end()); }
const_reverse_iterator rbegin() const
{ return const_reverse_iterator(end()); }
reverse_iterator rend()
{ return reverse_iterator(begin()); }
const_reverse_iterator rend() const
{ return const_reverse_iterator(begin()); }
//...
}
在上面的代码中,该类还定义了rbegin(),rend()等函数,可以返回容器的反向迭代器。
reverse_iterator类的定义如下:
template <class _RandomAccessIterator, class _Tp, class _Reference = _Tp&,
class _Distance = ptrdiff_t>
class reverse_iterator {
typedef reverse_iterator<_RandomAccessIterator, _Tp, _Reference, _Distance>
_Self;
protected:
_RandomAccessIterator current;
public:
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef _Tp* pointer;
typedef _Reference reference;
reverse_iterator() {}
explicit reverse_iterator(_RandomAccessIterator __x) : current(__x) {}
_RandomAccessIterator base() const { return current; }
_Reference operator*() const { return *(current - 1); }
#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;
}
_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); }
};
迭代器的前进,后退等操作都与普通迭代器的方向相反。
_Reference operator*() const { return *(current - 1); }
在解引用函数*定义中,函数先向前进一步,然后再对其解引用并返回,而正向迭代器则是直接解析其指向的元素。
stream iterator
流迭代器:将迭代器绑定到一个数据流(stream)对象上。包括istream_iterator和ostream_iterator。
stream_iterator --- istream_iterator
stream_iterator --- ostream_iterator
istream_iterator -.-> istream
ostream_iterator -.-> ostream
ostream_iterator
istream iterator在类的内部有一个istream类型的指针。当用户对迭代器进行操作时,迭代器内部通过该指针指向的输入流对象,完成相应的操作。
template <class _Tp, class _Dist>
class istream_iterator {
template <class _T1, class _D1>
friend bool operator==(const istream_iterator<_T1, _D1>&,
const istream_iterator<_T1, _D1>&);
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:
typedef input_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Dist difference_type;
typedef const _Tp* pointer;
typedef const _Tp& reference;
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*()); }
istream_iterator<_Tp, _Dist>& operator++() {
_M_read();
return *this;
}
istream_iterator<_Tp, _Dist> operator++(int) {
istream_iterator<_Tp, _Dist> __tmp = *this;
_M_read();
return __tmp;
}
};
类中istream类指针_M_stream实现迭代器的数据输入操作。_M_value变量保存最近输入的值。该类的默认构造函数用cin初始化_M_stream成员,并设置流输入结束符。用户也可以自己指定其他输入流(如文件流等)来初始化输入流指针成员_M_stream。
istream_iterator对象通常配合算法使用,可以用输入流完成对容器的初始化或赋值等功能。在算法中会调用istream_iterator对象的前进操作符号,而在自增操作符函数体中,调用了_M_read函数,在_M_read函数中,先判断是否到达流结尾,若未到达结尾,则调用输入流的operator>> ,将输入值赋给_M_value,并更新到达结尾状态。解引用操作符则可返回当前的最新输入值_M_value。每次对istream_iterator对象调用operator++,都会引发数据输入,并将输入值保存在缓存变量中。
ostream_iterator
ostream_iterator 类完成数据的输出操作。于istream_iterator的差别主要在赋值操作符operator=中:
ostream_iterator<_Tp>& operator=(const _Tp& __value) {
*_M_stream << __value;
if (_M_string) *_M_stream << _M_string;
return *this;
}
每次对ostream_iterator类对象调用赋值操作时,都会将右操作数 __value输出到指定的输出流中,并输入指定的分割字符串。
ostream_iterator类中封锁了其他几个操作符的功能,使得对其进行操作失效:
ostream_iterator<_Tp>& operator*() { return *this; }
ostream_iterator<_Tp>& operator++() { return *this; }
ostream_iterator<_Tp>& operator++(int) { return *this; }
STL 迭代器适配器(iterator adapter)的更多相关文章
- 疯子的算法总结(三) STL Ⅱ迭代器(iterator) + 容器
一.迭代器(Iterator) 背景:指针可以用来遍历存储空间连续的数据结构,但是对于存储空间费连续的,就需要寻找一个行为类似指针的类,来对非数组的数据结构进行遍历. 定义:迭代器是一种检查容器内元素 ...
- [C++ STL] 迭代器(iterator)详解
背景:指针可以用来遍历存储空间连续的数据结构,但是对于存储空间非连续的,就需要寻找一个行为类似指针的类,来对非数组的数据结构进行遍历.因此,我们引入迭代器概念. 一.迭代器(iterator)介绍 ...
- C++之STL迭代器(iterator)
[摘要]本文是对STL--迭代器(iterator)的讲解,对学习C++编程技术有所帮助,与大家分享. 原文:http://www.cnblogs.com/qunews/p/3761405.html ...
- 【C++ STL应用与实现】18: 怎样使用迭代器适配器
本系列文章的文件夹在这里:文件夹. 通过文件夹里能够对STL整体有个大概了解 前言 本文介绍了STL中的迭代器适配器(iterator adapter)的概念及其用法演示样例.迭代器适配器能够和标准库 ...
- STL之迭代器(iterator)
STL的中心思想在于:将数据容器和算法分开,彼此独立设计,最后再用一帖粘着剂将它们撮合在一起.没错,这个粘着剂正是迭代器(iterator).迭代器的主要目的是通过遍历来对容器中元素进行相关操作.算法 ...
- function adapter(函数适配器)和迭代器适配器
所谓function adapter(函数适配器)是指能够将不同的函数对象(或是和某值或某寻常函数)结合起来的东西,它自身也是个函数对象. 迭代器适配器 运用STL中的迭代器适配器,可以使得算法能够 ...
- STL源码剖析 迭代器(iterator)概念与编程技法(三)
1 STL迭代器原理 1.1 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型,STL设计的精髓在于,把容器(Containers)和算法(Algorithms)分开,而迭代器(i ...
- 【C++】:STL迭代器使用---[容器::iterator iter;]
参考文章:http://blog.csdn.net/qq_23100787/article/details/51388163 迭代器这种东西,就是为了使访问简单!! 容器::iterator iter ...
- STL标准库-迭代器适配器
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 这次主要介绍一下迭代器适配器.以reverse_iterator(反向迭代器),insert_iterator(插入迭代器),o ...
随机推荐
- 深度强化学习(Deep Reinforcement Learning)入门:RL base & DQN-DDPG-A3C introduction
转自https://zhuanlan.zhihu.com/p/25239682 过去的一段时间在深度强化学习领域投入了不少精力,工作中也在应用DRL解决业务问题.子曰:温故而知新,在进一步深入研究和应 ...
- CF1103D Codeforces Round #534 (Div. 1) Professional layer 状压 DP
题目传送门 https://codeforces.com/contest/1103/problem/D 题解 失去信仰的低水平选手的看题解的心路历程. 一开始看题目以为是选出一些数,每个数可以除掉一个 ...
- RAC heartbeat 心跳机制
世界上最遥远的距离,不是生与死.而是我们同一个集群的两个节点,你却听不到我的心跳. 必要性:维持集群的⼀致性RAC⼼跳机制 – 集群⼼跳基本机制:1.确定节点和节点间的连通性,达到彼此了解2.⽤共享的 ...
- Github使用进阶
1 Github常用词: watch:会持续收到该项目的动态 fork:复制某个项目到自己的Github仓库中 star:可以理解为点赞 clone:将项目下载至本地 follow:关注你感兴趣的作者 ...
- 半小时写完替罪羊重构点分树做动态动态点分治之紫荆花之恋的wyy贴心指导
刷题训练 初学者 有一定语言基础,但是不了解算法竞赛,水平在联赛一等奖以下的. 参考书:<算法竞赛入门经典--刘汝佳>,<算法竞赛入门经典训练指南--刘汝佳> 题库:洛谷(历年 ...
- WPF 远程显示原图 当前主页面 工具栏 一个Window页面的元素适用一个效果
http://www.jb51.net/article/98384.htm 1.wpf远程显示原图: Stretch="Fill" + ; 主要是因为那个950和650,据显示位置 ...
- HTML和CSS实现的透明登录框效果
实现代码 HTML部分 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- HDU 6153 A Secret ( KMP&&DP || 拓展KMP )
题意 : 给出两个字符串,现在需要求一个和sum,考虑第二个字符串的所有后缀,每个后缀对于这个sum的贡献是这个后缀在第一个字符串出现的次数*后缀的长度,最后输出的答案应当是 sum % 1e9+7 ...
- 一次傻乎乎的错误QAQ
东北联赛上有一道题,数据范围是2^60,当时不记得long long的范围,于是写了一个程序试了一下,把队友带入了一个大数的大坑QAQ(蠢哭). 当时写的代码是这样的: #include<ios ...
- R list和data frame 排序
pathway_name = rownames(g1) tm <- list('P-value' = c(), 'Pathway_name' = c()) :dim(g1)[]){ result ...