STL标准库-迭代器适配器
技术在于交流、沟通,本文为博主原创文章转载请注明出处并保持作品的完整性
这次主要介绍一下迭代器适配器.以reverse_iterator(反向迭代器),insert_iterator(插入迭代器),ostream_iterator(输出迭代器)迭代器和算法中的copy函数做参考
迭代器适配器主要运用包含及操作符重载实现(主要操作符重载有operator*,operator=,operator++,operator--)
其实本节主要就是介绍运算符重载
1.reverse_iterator反向迭代器的实现
下面是reverse_iterator的源码
template<typename _Iterator>
class reverse_iterator
: public iterator<typename iterator_traits<_Iterator>::iterator_category,
typename iterator_traits<_Iterator>::value_type,
typename iterator_traits<_Iterator>::difference_type,
typename iterator_traits<_Iterator>::pointer,
typename iterator_traits<_Iterator>::reference>
{
protected:
_Iterator current; typedef iterator_traits<_Iterator> __traits_type; public:
typedef _Iterator iterator_type;
typedef typename __traits_type::difference_type difference_type;
typedef typename __traits_type::pointer pointer;
typedef typename __traits_type::reference reference; /**
* The default constructor value-initializes member @p current.
* If it is a pointer, that means it is zero-initialized.
*/
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 235 No specification of default ctor for reverse_iterator
reverse_iterator() : current() { } /**
* This %iterator will move in the opposite direction that @p x does.
*/
explicit
reverse_iterator(iterator_type __x) : current(__x) { } /**
* The copy constructor is normal.
*/
reverse_iterator(const reverse_iterator& __x)
: current(__x.current) { } /**
* A %reverse_iterator across other types can be copied if the
* underlying %iterator can be converted to the type of @c current.
*/
template<typename _Iter>
reverse_iterator(const reverse_iterator<_Iter>& __x)
: current(__x.base()) { } /**
* @return @c current, the %iterator used for underlying work.
*/
iterator_type
base() const
{ return current; } /**
* @return A reference to the value at @c --current
*
* This requires that @c --current is dereferenceable.
*
* @warning This implementation requires that for an iterator of the
* underlying iterator type, @c x, a reference obtained by
* @c *x remains valid after @c x has been modified or
* destroyed. This is a bug: http://gcc.gnu.org/PR51823
*/
reference
operator*() const
{
_Iterator __tmp = current;
return *--__tmp;
} /**
* @return A pointer to the value at @c --current
*
* This requires that @c --current is dereferenceable.
*/
pointer
operator->() const
{ return &(operator*()); } /**
* @return @c *this
*
* Decrements the underlying iterator.
*/
reverse_iterator&
operator++()
{
--current;
return *this;
} /**
* @return The original value of @c *this
*
* Decrements the underlying iterator.
*/
reverse_iterator
operator++(int)
{
reverse_iterator __tmp = *this;
--current;
return __tmp;
} /**
* @return @c *this
*
* Increments the underlying iterator.
*/
reverse_iterator&
operator--()
{
++current;
return *this;
} /**
* @return A reverse_iterator with the previous value of @c *this
*
* Increments the underlying iterator.
*/
reverse_iterator
operator--(int)
{
reverse_iterator __tmp = *this;
++current;
return __tmp;
} /**
* @return A reverse_iterator that refers to @c current - @a __n
*
* The underlying iterator must be a Random Access Iterator.
*/
reverse_iterator
operator+(difference_type __n) const
{ return reverse_iterator(current - __n); } /**
* @return *this
*
* Moves the underlying iterator backwards @a __n steps.
* The underlying iterator must be a Random Access Iterator.
*/
reverse_iterator&
operator+=(difference_type __n)
{
current -= __n;
return *this;
} /**
* @return A reverse_iterator that refers to @c current - @a __n
*
* The underlying iterator must be a Random Access Iterator.
*/
reverse_iterator
operator-(difference_type __n) const
{ return reverse_iterator(current + __n); } /**
* @return *this
*
* Moves the underlying iterator forwards @a __n steps.
* The underlying iterator must be a Random Access Iterator.
*/
reverse_iterator&
operator-=(difference_type __n)
{
current += __n;
return *this;
} /**
* @return The value at @c current - @a __n - 1
*
* The underlying iterator must be a Random Access Iterator.
*/
reference
operator[](difference_type __n) const
{ return *(*this + __n); }
};
我们主要以几个比较明显的表示其适配器特征的函数为例
template<typename _Iterator>
class reverse_iterator
: public iterator<typename iterator_traits<_Iterator>::iterator_category,
typename iterator_traits<_Iterator>::value_type,
typename iterator_traits<_Iterator>::difference_type,
typename iterator_traits<_Iterator>::pointer,
typename iterator_traits<_Iterator>::reference>
{
protected:
_Iterator current;//对应的正向迭代器 typedef iterator_traits<_Iterator> __traits_type;//迭代器萃取机 public:
typedef _Iterator iterator_type;//逆向迭代器的5中associated types 和其他迭代器相同
typedef typename __traits_type::difference_type difference_type;
typedef typename __traits_type::pointer pointer;
typedef typename __traits_type::reference reference; //构造函数
reverse_iterator() : current() { }
explicit
reverse_iterator(iterator_type __x) : current(__x) { }
reverse_iterator(const reverse_iterator& __x)
: current(__x.current) { } //取出对应的正向迭代器
iterator_type
base() const
{ return current; } //关键点在这里, *操作取值,取对应正向迭代器的上一位
reference
operator*() const
{
_Iterator __tmp = current;
return *--__tmp;
} pointer
operator->() const
{ return &(operator*()); } //前进变后退 后退变前进
reverse_iterator&
operator++()
{
--current;
return *this;
} reverse_iterator
operator++(int)
{
reverse_iterator __tmp = *this;
--current;
return __tmp;
} reverse_iterator&
operator--()
{
++current;
return *this;
} reverse_iterator
operator--(int)
{
reverse_iterator __tmp = *this;
++current;
return __tmp;
} reverse_iterator
operator+(difference_type __n) const
{ return reverse_iterator(current - __n); } reverse_iterator&
operator+=(difference_type __n)
{
current -= __n;
return *this;
} reverse_iterator
operator-(difference_type __n) const
{ return reverse_iterator(current + __n); } reverse_iterator&
operator-=(difference_type __n)
{
current += __n;
return *this;
} reference
operator[](difference_type __n) const
{ return *(*this + __n); }
};
下面是反向迭代器的起点和终点函数及图解
reverse_iterator rbegin()
{
return reverse_iterator(end());
} reverse_iterator rend()
{
return reverse_iterator(begin());
}

总结 反向迭代器,它包含其正向迭代器,使用重载其原来的operator*,operator++等操作实现其反向功能
2.insert_iterator
首先看一下算法中的copy函数源码(G2.9)
template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last)
{
*result = * first;
++result;
++first;
}
}
注意copy()函数中没有申请新的内存,采取的方式是直接赋值,那么当内存不够使用时,调用copy函数会报错
namespace wzj009 {
void test_Insert_Iterator()
{
int myArray[] = {,,,,,,};
vector<int> v1;
v1.resize();//申请内存为6
copy(myArray, myArray + , v1.begin());//copy7个元素过来导致越界
for(auto i : v1)
{
cout << i << endl;
}
}
}

现在我们看下面这段代码是够能够编译通过
namespace wzj010 {
void test_Insert_Iterator()
{
int myArray[] = {,,,,,,};
vector<int> v1;
v1.resize();
copy(myArray, myArray + , inserter(v1,v1.begin()));
for(auto i : v1)
{
cout << i << endl;
}
}
}

我们从copy的源码中可以看得出,它的每一个方法都是写死的,那么为什么这几就能编译通过,这份功劳应该归功于运算符重载,因为insert方法会调用到insert_iterator,而insert_iterator重载了operator=,进而实现了该功能
我们看一下insert_iterator的源码
template<typename _Container>
class insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
protected:
_Container* container;
typename _Container::iterator iter; public:
typedef _Container container_type; insert_iterator(_Container& __x, typename _Container::iterator __i)
: container(&__x), iter(__i) {} …
insert_iterator&
operator=(const typename _Container::value_type& __value)
{
iter = container->insert(iter, __value);
++iter;
return *this;
} insert_iterator&
operator=(typename _Container::value_type&& __value)//关键点在这里,它重载了operator= 使copy函数中的 *result = * first; 调用这里的operator函数
{
iter = container->insert(iter, std::move(__value));
++iter;
return *this;
}
…
}
template<typename _Container, typename _Iterator>
inline insert_iterator<_Container>
inserter(_Container& __x, _Iterator __i)
{
return insert_iterator<_Container>(__x,
typename _Container::iterator(__i));
}//这个函数使insert调用insert_iterator
虽然运算符重载有时使我们很难读懂代码,但其功能是非常强大的
3 ostream_iterator
看下面代码
namespace wzj011 {
void test_ostream_iterator()
{
vector<int> v;
for(int i = ;i<; i++) v.push_back(i*);
std::ostream_iterator<int> out_it(std::cout, "-");//将将std::cout绑定在out_it,并且输出每个元素时加以"-"
copy(v.begin(),v.end(),out_it);
}
}

我紧紧是将v copy给 out_it 却输出了out_it内的元素, 那么此时我的copy功能实现了其std::cout,那么copy函数这个功能任然要归功于函数重载
template<typename _Tp, typename _CharT = char,
typename _Traits = char_traits<_CharT> >
class ostream_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
…
private:
ostream_type* _M_stream;
const _CharT* _M_string; public:
/// Construct from an ostream.
ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string() {}//std::ostream_iterator<int> out_it(std::cout, “-“)将_M_stream 绑定为std::cout “-“赋值给_M_string ostream_iterator(ostream_type& __s, const _CharT* __c)
: _M_stream(&__s), _M_string(__c) { } /// Copy constructor.
ostream_iterator(const ostream_iterator& __obj)
: _M_stream(__obj._M_stream), _M_string(__obj._M_string) { } /// Writes @a value to underlying ostream using operator<<. If
/// constructed with delimiter string, writes delimiter to ostream.
ostream_iterator&
operator=(const _Tp& __value)//
{
__glibcxx_requires_cond(_M_stream != ,
_M_message(__gnu_debug::__msg_output_ostream)
._M_iterator(*this));
*_M_stream << __value;//将value传递给_M_stream 使其作出输出动作
if (_M_string) *_M_stream << _M_string;
return *this;
}
…
};
以上的三种迭代器适配器都非常好理解,更重要的是在于我们要理解他的设计理念,运算重载功能非常强大,要好好利用
参考侯捷<<STL源码剖析>>
STL标准库-迭代器适配器的更多相关文章
- STL标准库-容器适配器
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 上一节介绍了仿函数适配器,这节主要介绍容器适配器和迭代器适配器的概念,其实容器适配器和迭代器其适配器就是封装了一些其他class ...
- STL标准库-迭代器
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 本节主要介绍STL六大部件中的Iterators迭代器. 在语言方面讲,容器是一个class template, 算法是一个仿函 ...
- STL标准库-容器-set与multiset
技术在于交流.沟通,转载请注明出处并保持作品的完整性. set与multiset关联容器 结构如下 set是一种关联容器,key即value,value即key.它是自动排序,排序特点依据key se ...
- STL标准库-算法-常用算法
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 介绍11种STL标准库的算法,从这11种算法中总结一下算法的基本使用 1.accumulate() 累加 2.for_each( ...
- STL标准库-容器-deque
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. deque双向开口可进可出的容器 我们知道连续内存的容器不能随意扩充,因为这样容易扩充别人那去 deque却可以,它创造了内存 ...
- STL标准库-容器-vector
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. 向量容器vector是一个动态数组,内存连续,它是动态分配内存,且每次扩张的原来的二倍. 他的结构如下 一 定义 vector ...
- C++STL标准库学习笔记(五)set
前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标记了出来,这一篇后面主要都是我的记录了,为了防止大片蓝色字体出现,后面就不改蓝色 ...
- C++STL标准库学习笔记(三)multiset
C++STL标准库学习笔记(三)multiset STL中的平衡二叉树数据结构 前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标 ...
- c/c++ 标准库 迭代器(iterator)
c/c++ 标准库 迭代器 begin和end运算符返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator:如果对象不是常量,返回iteraotor 1 ...
随机推荐
- 【Coursera】Security Introduction -Ninth Week(1)
前言 Coursera 的 Internet History,Technology,and Security 进入最后一周的学习了,在这最后一周内,需要进行的内容是 public-key 公钥系统的讲 ...
- UVa 11212 编辑书稿(dfs+IDA*)
https://vjudge.net/problem/UVA-11212 题意:给出n个自然段组成的文章,将他们排列成1,2...,n.每次只能剪切一段连续的自然段,粘贴时按照顺序粘贴. 思路:状态空 ...
- go 并发
package main import ( "fmt" "time" ) func say(s string) { ; i < ; i++ { time. ...
- python网络编程之TCP通信实例
一. server.py import socket host="localhost" port= s=socket.socket(socket.AF_INET,socket.SO ...
- vmstat命令中System下in cs 何时为高?
https://superuser.com/ https://serverfault.com/ 良好状态指标 CPU利用率:User Time <= 70%,System Time <= ...
- Beta冲刺
第一天 日期:2018/6/24 1 今日完成任务情况. 妥志福.牛瑞鑫: 完成任务:数据库设计完成数据导入成功 王胜海.马中林: 完成任务:代码规范检查 董润园.邓英蓉: 完成任务:平台基本功能黑盒 ...
- grafana 批量添加图表
利用grafana做监控展示特别方便,而且界面还很有科技感,一般的使用都是自己手动添加图表,或者使用别人提供好的模板. 在一种情况下就比较尴尬了,我有100个实例的内存数据想展示,如果都放在一个tab ...
- Python爬虫Urllib库的基本使用
Python爬虫Urllib库的基本使用 深入理解urllib.urllib2及requests 请访问: http://www.mamicode.com/info-detail-1224080.h ...
- js和css兼容问题
(一)html部分 1.H5新标签在IE9以下的浏览器识别 <!--[if lt IE 9]> <script type="text/javascript" s ...
- Mac下使用源码编译安装TensorFlow CPU版本
1.安装必要的软件 1.1.安装JDK 8 (1)JDK 8 can be downloaded from Oracle's JDK Page: http://www.oracle.com/techn ...