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 ...
随机推荐
- Java中++,--,前缀后缀表达值的不同,与^的值计算
package 习题1; /** * ++ -- 与 ^ 的一些计算 * @author SeeClanUkyo * */ public class Test4 { public static voi ...
- left join联查提高执行性能
本文为博主原创,未经允许不得转载: 在项目应用中,很多功能需要多张数据库表联查,甚至跨数据库查询获取数据.sql的执行性能很能影响 服务的体验感,今天就遇到了这样问题,原来的sql是这样的: sele ...
- 转:java项目经验面试总结
转载: 在前期已经讲过怎样分析自己,对自己进行一个准确的定位,选择一个合适的求职方向!并结合自己的实际个人情况来写一份针对性很强的个人简历!个人简历就是个人的广告!好的简历可以更受到用人需求单位青睐! ...
- Seleniumz中 dr.quit()和dr.close()的区别
/** * dr.quit()和dr.close()都可以退出浏览器,简单的说一下两者的区别:第一个close, * 如果打开了多个页面是关不干净的,它只关闭当前的一个页面.第二个quit, * 是退 ...
- 【转】总结C++中取成员函数地址的几种方法
转自:“http://www.cnblogs.com/nbsofer/p/get_member_function_address_cpp.html” 这里, 我整理了4种C++中取成员函数地址的方法, ...
- [STL][C++]LIST
参考:http://blog.csdn.net/whz_zb/article/details/6831817 list是双向循环链表,,每一个元素都知道前面一个元素和后面一个元素.在STL中,list ...
- 统计字符串中每个字符出现的次数(Python)
#统计字符串中每个字符出现的次数 以The quick brown fox jumps over the lazy dog为例 message='The quick brown fox jumps o ...
- 《WAP团队项目软件设计方案》
WAP团队项目软件设计方案 一.根据OOD详细设计工作要点,修改完善团队项目系统设计说明书和详细设计说明文档的GitHub地址:https://github.com/LVowe999/-7.git 在 ...
- 语言小知识-MySQL数据库引擎
MySQL作为全世界广受欢迎的数据库,被用于很多中小型的项目中,但是你对 MySQL 数据库的存储引擎了解多少呢? 我们将逻辑表中的数据存储到数据库中,数据库又将我们表中的数据存储到物理设备中(如磁盘 ...
- robot脚本编写规范
一个robot脚本主要有四部分组成: ***settings*** 设置 ***keywords*** 关键词 ***variables*** 变量 ***test cases*** 测试用例 一般, ...