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 ...
随机推荐
- C#学习笔记(十):函数和参数
函数 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syste ...
- UOJ 171 【WC2016】挑战NPC
一开始还真没想到是一般图匹配这种模型(毕竟才会的带花树) 把每一个盒子拆成3个,每一个可以放置进它的小球分别向这三个点连边,然后这三个点在连成一个三元环,最终答案就是小球数目-匹配数. 由于是一般图, ...
- vue router菜单 存在点哪个但还是会显示active
<router-link to="/" exact>Home</router-link> <router-link to="/add&quo ...
- go 变量声明
第一种,指定变量类型,声明后若不赋值,使用默认值. var v_name v_type v_name = value 第二种,根据值自行判定变量类型. var v_name = value 第三种,省 ...
- c++ 数组元素拷贝到容器(copy)
#include <iostream> // cout #include <algorithm> // copy #include <vector> // vect ...
- pyCharm最新2017激活码
pyCharm最近激活码过期,找到一个最新的activation code,可用期为2017一年.如下: BIG3CLIK6F-eyJsaWNlbnNlSWQiOiJCSUczQ0xJSzZGIiwi ...
- django查询集API
本节将详细介绍查询集的API,它建立在下面的模型基础上,与上一节的模型相同: from django.db import models class Blog(models.Model): name = ...
- 统计字符串中每个字符出现的次数(Python)
#统计字符串中每个字符出现的次数 以The quick brown fox jumps over the lazy dog为例 message='The quick brown fox jumps o ...
- 《A_Pancers》团队作业6—团队项目系统设计改进与详细设计
一.团队项目系统设计改进: 1.分析项目系统设计说明书初稿的不足,特别是软件系统结构模型建模不完善内容: 在上一次的项目系统设计说明书中没有很好的完成软件系统结构模型的建模设计,只做了基本的系统项目原 ...
- js、jq对象互转
1.js对象转jq对象: $() $('#kw') $(document.getElementById("kw")) 2.jq对象转js对象: $(this).get(0) ...