STL(十):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}
来源:互联网 发布:c语言入门看什么书 编辑:程序博客网 时间:2024/05/16 13:44
一、迭代器适配器
反向迭代器
插入迭代器
IO流迭代器
其中反向迭代器可以参考以前的文章。
二、插入迭代器
插入迭代器实际上是一个输出迭代器(*it=; ++)
back_insert_iterator
back_inserter
front_insert_iterator
front_inserter
先来看示例:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <vector>
#include <algorithm>
using namespace std;
void ShowVec(const vector<int> &v)
{
for (vector<int>::const_iterator it = v.begin(); it != v.end(); ++it)
{
cout << *it << ' ';
}
cout << endl;
}
int main(void)
{
int a[] = {1, 2, 3, 4, 5};
vector<int> v(a, a + 5);
vector<int> v2;
back_insert_iterator<vector<int> > bii(v);
//*bii = 6;
bii = 6;
ShowVec(v);
back_insert_iterator<vector<int> > bii2(v2);
copy(v.begin(), v.end(), bii2);
ShowVec(v2);
back_inserter(v) = 7;
ShowVec(v);
copy(v.begin(), v.end(), back_inserter(v2));
ShowVec(v2);
return 0;
}
查看back_insert_iterator 类的定义:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
template<class _Container>
class back_insert_iterator
: public _Outit
{
// wrap pushes to back of container as output iterator
public:
typedef _Container container_type;
typedef typename _Container::reference reference;
typedef _Range_checked_iterator_tag _Checked_iterator_category;
explicit back_insert_iterator(_Container &_Cont)
: container(&_Cont)
{
// construct with container
}
back_insert_iterator<_Container> &operator=(
typename _Container::const_reference _Val)
{
// push value into container
container->push_back(_Val);
return (*this);
}
back_insert_iterator<_Container> &operator*()
{
// pretend to return designated value
return (*this);
}
back_insert_iterator<_Container> &operator++()
{
// pretend to preincrement
return (*this);
}
back_insert_iterator<_Container> operator++(int)
{
// pretend to postincrement
return (*this);
}
protected:
_Container *container; // pointer to container
};
类内部的成员container 保存的是指向容器的指针,重载了*, ++, = 等运算符,* 和 ++ 返回的都是迭代器本身,主要看 赋值运算符:
container->push_back(_Val); 即调用了容器的push_back 函数, 所以可以直接写 bii = 6; 即将6压入容器末尾。程序中还调用了copy
函数,回顾copy 源码,主要是以下代码:
for (; _First != _Last; ++_Dest, ++_First)
*_Dest = *_First;
其中,_First 和 _Last 分别是v.begin() 和 v.end(), _Dest 是 bii2,上面也说了,*_Dest 返回的是自身,而且++_Dest 返回的也是自
身,从_First 遍历到 _Last ,调用back_insert_iterator 类的operator=,即不断地执行container->push_back(_Val); 容器的元素位置会
自动移动。
再来看back_inserter 函数:
2
3
4
5
6
7
template<class _Container> inline
back_insert_iterator<_Container> back_inserter(_Container &_Cont)
{
// return a back_insert_iterator
return (std::back_insert_iterator<_Container>(_Cont));
}
实际上返回的也是一个back_insert_iterator 对象,所以能直接替换掉bii2。
当然了,与back 配对的就是front,back 是末尾插入,front 是头端插入,需要注意的是front_insert_iterator 的operator= 调用了
push_front 函数,故如vector 是没有实现push_front 的,不能使用front_insert_iterator ,而list 和 deque 是可以使用的。
示例代码如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
void ShowList(const list<int> &v)
{
for (list<int>::const_iterator it = v.begin(); it != v.end(); ++it)
{
cout << *it << ' ';
}
cout << endl;
}
int main(void)
{
int a[] = {1, 2, 3, 4, 5};
list<int> l(a, a + 5);
list<int> ll;
front_insert_iterator<list<int> > fii(l);
fii = 0;
ShowList(l);
copy(l.begin(), l.end(), front_inserter(ll));
ShowList(ll);
return 0;
}
三、IO流迭代器
输出流迭代器(ostream_iterator)
*it=; ++
输入流迭代器(istream_iterator)
=*it; ->; ++; ==; !=
直接来看示例代码:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
int main(void)
{
vector<int> v;
// copy from cin to vector
copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(v));
// copy from vector to cout
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
首先来看istream_iterator 的源码:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
template < class _Ty,
class _Elem = char,
class _Traits = char_traits<_Elem>,
class _Diff = ptrdiff_t >
class istream_iterator
: public iterator < input_iterator_tag, _Ty, _Diff,
const _Ty *, const _Ty & >
{
// wrap _Ty extracts from input stream as input iterator
typedef istream_iterator<_Ty, _Elem, _Traits, _Diff> _Myt;
public:
typedef _Elem char_type;
typedef _Traits traits_type;
typedef basic_istream<_Elem, _Traits> istream_type;
#if _SECURE_SCL
typedef _Range_checked_iterator_tag _Checked_iterator_category;
#endif
istream_iterator()
: _Myistr(0)
{
// construct singular iterator
}
istream_iterator(istream_type &_Istr)
: _Myistr(&_Istr)
{
// construct with input stream
_Getval();
}
const _Ty &operator*() const
{
// return designated value
return (_Myval);
}
const _Ty *operator->() const
{
// return pointer to class object
return (& **this);
}
_Myt &operator++()
{
// preincrement
_Getval();
return (*this);
}
protected:
void _Getval()
{
// get a _Ty value if possible
if (_Myistr != 0 && !(*_Myistr >> _Myval))
_Myistr = 0;
}
istream_type *_Myistr; // pointer to input stream
_Ty _Myval; // lookahead value (valid if _Myistr is not null)
};
istream_iterator 类有两个成员,一个是输入流对象指针,一个是输入的值,如
istream_iterator<int>(cin) 调用构造函数,初始化_Myistr,且通过函数_Getval() 初始化_Myval,_Getval() 调用输入流的
operator>> 将键盘输入的值赋予_Myval。而 istream_iterator<int>() 呢初始化_Myistr 为0,此时_Myval 被忽略。
回顾copy 源码,主要是以下代码:
for (; _First != _Last; ++_Dest, ++_First)
*_Dest = *_First;
此时_First 和 _Last 是 istream_iterator<int> 类型,_Dest是back_insert_iterator 类型,而判断_First 和 _Last 是否相等,其实
operator != 里面是判断它们的成员指针_Myistr 是否相等,在_Getval 函数可以看到,当我们输入错误(类型不匹配)或者ctrl+z,
如果不等,即输入正确的话,*First 调用istream_iterator 类的operator* 直接返回_Myval ,接着调用back_insert_iterator 类的
istream_iterator 类的
operator++ 中会继续调用_Getval,即继续获得键盘输入覆盖_Myval。
再来看ostream_iterator 的源码:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
template<class _Ty,
class _Elem = char,
class _Traits = char_traits<_Elem> >
class ostream_iterator
: public _Outit
{ // wrap _Ty inserts to output stream as output iterator
public:
typedef _Elem char_type;
typedef _Traits traits_type;
typedef basic_ostream<_Elem, _Traits> ostream_type;
#if _SECURE_SCL
typedef _Range_checked_iterator_tag _Checked_iterator_category;
#endif
ostream_iterator(ostream_type& _Ostr,
const _Elem *_Delim = 0)
: _Myostr(&_Ostr), _Mydelim(_Delim)
{ // construct from output stream and delimiter
}
ostream_iterator<_Ty, _Elem, _Traits>& operator=(const _Ty& _Val)
{ // insert value into output stream, followed by delimiter
*_Myostr << _Val;
if (_Mydelim != 0)
*_Myostr << _Mydelim;
return (*this);
}
ostream_iterator<_Ty, _Elem, _Traits>& operator*()
{ // pretend to return designated value
return (*this);
}
ostream_iterator<_Ty, _Elem, _Traits>& operator++()
{ // pretend to preincrement
return (*this);
}
protected:
const _Elem *_Mydelim; // pointer to delimiter string (NB: not freed)
ostream_type *_Myostr; // pointer to output stream
};
ostream_iterator 类也有两个成员,一个是输出流对象指针,一个是字符串指针,看上面的copy 代码,此时_First 和 _Last
ostream_iterator<int>
*_Myostr << _Val;
if (_Mydelim != 0)
*_Myostr << _Mydelim;
即判断如果还有传入字符串,则在输出元素值之后,还伴随着字符串的输出。所以示例代码中的输出是伴随着空格的。
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
- C++之STL(十):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}
- STL(十):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}
- 从零开始学C++之STL(十):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}
- 从零开始学C++之STL(十):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}
- 6种常用的迭代器 ostream_iterator,istream_iterator,reverse_iterator,back_insert_iterator,front_insert_itera)
- istream_iterator ostream_iterator 迭代器和IO
- STL适配器(ostream_itertor与istream_iterator)
- STL istream_iterator & ostream_iterator demo
- C++中流迭代器istream_iterator 和 ostream_iterator的使用
- istream_iterator ostream_iterator
- c++使用流迭代器istream_iterator和ostream_iterator
- 29 x适配器ostream_iterator和istream_iterator(学自Boolean)
- STL中istream_iterator和ostream_iterator的基本用法
- STL中istream_iterator和ostream_iterator的基本用法
- 初学istream_iterator(转)
- istream_iterator和ostream_iterator学习体会
- istream_iterator、ostream_iterator 使用初探
- istream_iterator和ostream_iterator
- 《快来看一只老鼠下了13只小老鼠》
- STL(九):函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例
- cocos2dx 3.2版本获得精灵缩放后的尺寸大小
- 你理解我的意思么?
- 中国顶级黑客的生意—---在商业利益与社会责任间两难抉择
- STL(十):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}
- cocos2d-x 弹入、弹出效果(以菜单为例子)
- 项目准备
- HDU - 1002 A + B Problem II
- 指针高级的应用
- python 笔记一 numpy,pylab
- 【呆子谈营销】:说说那些热点事情之后的借势营销
- Linux下动态库(.so)和静态库(.a) 的区别
- SecureCRT进入全屏和退出全屏