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 ...
随机推荐
- deletefile 与KILL
1.Kill 语句 从磁盘中删除文件.语法Kill pathname必要的 pathname 参数是用来指定一个文件名的字符串表达式.pathname 可以包含目录或文件夹.以及驱动器.说明在 Mic ...
- dying relu 和weight decay
weight decay就是在原有loss后面,再加一个关于权重的正则化,类似与L2 正则,让权重变得稀疏: 参考:https://www.zhihu.com/question/24529483 dy ...
- hdu 3530 单调队列最值
/** HDU 3530 单调队列的应用 题意: 给定一段序列,求出最长的一段子序列使得该子序列中最大最小只差x满足m<=x<=k. 解题思路: 建立两个单调队列分别递增和递减维护(头尾删 ...
- Linux 安装 Composer
Linux 安装 Composer 入门 练习环境: 虚拟机:Oracle VM VirtualBox. 系统:CentOS 7. 安装方式一: 参考网址:https://learnku.com/c ...
- Qt学习笔记-Widget布局管理
Qt学习笔记4-Widget布局管理 以<C++ GUI Programming with Qt 4, Second Edition>为参考 实例:查找对话框 包含三个文件,f ...
- LeetCode--072--编辑距离(python)
给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 . 你可以对一个单词进行如下三种操作: 插入一个字符删除一个字符替换一个字符示例 1: 输入: ...
- Python自动化运维技术与最佳实现
第一章 系统基础信息模块详解 系统基础信息采集模块最为监控模块的重要组成部分,能够帮助运维人员了解当前系统的健康程度,同时也是衡量业务的服务质量的依据,比如系统资源吃紧,会直接影响业务的质量以及用户的 ...
- React Native 之ScrollView
import React, { Component } from 'react' import { Text, StyleSheet, View, Button ,TouchableOpacity,A ...
- jQuery 遍历 - 同胞(siblings)
同胞拥有相同的父元素. 通过 jQuery,您能够在 DOM 树中遍历元素的同胞元素. 在 DOM 树中水平遍历 有许多有用的方法让我们在 DOM 树进行水平遍历: siblings() next() ...
- SpringBoot整合knife4j
官网说明及用法: 简介 swagger-bootstrap-ui是springfox-swagger的增强UI实现,为Java开发者在使用Swagger的时候,能拥有一份简洁.强大的接口文档体验 核心 ...