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 ...
随机推荐
- PAT Advanced 1006 Sign In and Sign Out (25 分)
At the beginning of every day, the first person who signs in the computer room will unlock the door, ...
- Python小技巧:使用*解包和itertools.product()求笛卡尔积(转)
leetcode上做提示时候看到有高人用这个方法解题 [问题] 目前有一字符串s = "['a', 'b'],['c', 'd']",想把它分开成为两个列表: list1 = [' ...
- 牛客练习赛14 B 区间的连续段 (倍增)
链接:https://ac.nowcoder.com/acm/contest/82/B来源:牛客网 区间的连续段 时间限制:C/C++ 7秒,其他语言14秒 空间限制:C/C++ 262144K,其他 ...
- Codeforces 957 水位标记思维题
A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...
- python set 集合操作
转自:https://www.cnblogs.com/alex3714/articles/5740985.html s = set([3,5,9,10]) #创建一个数值集合 t = set(&quo ...
- python 小游戏,和电脑玩剪刀石头布
# -*- coding: utf-8 -*- """ Created on Fri Oct 25 16:28:12 2019 if判断综合演练,剪刀石头布 @autho ...
- DUBBO原理、应用与面经总结
研读dubbo源码已经有一段时间了,dubbo中有非常多优秀的设计模式和示例代码值得学习,但是dubbo的调用层级和方法链都较为繁杂,如果不对源码思路进行梳理则很容易忘却,因此总结一篇研读心得,从阅读 ...
- 【leetcode】827. Making A Large Island
题目如下: 解题思路:这个题目可以进行拆分成几个子问题.第一,求出island的数量,其实就是 200. Number of Islands,这个很简单,DFS或者BFS都能搞定:第二,除了求出isl ...
- [USACO2019JAN]Sleepy Cow Sorting题解
拿到这个问题,我们从头开始思考. 我们把序列看做两部分,一部分在前表示待排序的,记为序列1,一部分在后表示已排序的,记为序列2. 因为序列2在后,所以不必担心它影响序列1的排序,那么对于序列1的第一个 ...
- warp(图像仿射变换)
仿射变换是一种二维坐标(x,y)到二维坐标(u,v)的线性变换. 对应的齐次坐标矩阵表示形式为: 仿射变换特点: 直线经仿射变换后依然为直线: ’直线之间的相对位置关系保持不变,平行线经仿射变换后依然 ...