STL之迭代器(iterator)
迭代器的基本概念
迭代器(iterator)模式又称为游标(Cursor)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。或者这样说可能更容易理解:Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。
迭代器产生原因(或者本质)
Iterator
类的访问方式就是把不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循环遍历集合的效果。
迭代器的类型
输入迭代器
(
InputIterator
)
、输出迭代器
(
OutputIterator
)
、前向迭代器(ForwardIterator
)
、双向迭代器
(
BidirectionalIterator
)
、随机访问迭代器(RandomAccessIterator
)
。
每个迭代器类型对应的操作。
类别
简写
|
输出
output
|
输入
input
|
前向
Forward
|
双向
Bidirection
|
随机
Random
|
读
|
=*
p
| =*p | =*p | =*p | |
访问
|
->
|
->
|
->
|
-> []
| |
写
|
*
p
=
| *p= | *p= | *p= | |
迭代
|
++
| ++ | ++ |
++/--
|
++/--/+/-/+=/-=
|
比较
|
==/!=
|
==/!=
|
==/!=
|
==/!=/</>/<=/>=
|
五种迭代器之间的关系图
为什么定义这么多迭代器
物尽其用,使得具体的操作使用具体类型的迭代器,避免迭代器的功能太大或者太小,导致使用起来不方便。每个容器及其对应的迭代器的类型图表如下:
容器
|
类内迭代器类别
|
vector |
随机访问迭代器
|
deque |
随机访问迭代器
|
list |
双向迭代器
|
set |
双向迭代器
|
multiset |
双向迭代器
|
map |
双向迭代器
|
multimap |
双向迭代器
|
unordered_set |
前向迭代器
|
unordered_multiset |
前向迭代器
|
unordered_map |
前向迭代器
|
unordered_multimap |
前向迭代器
|
流迭代器
流迭代器是特殊的迭代器,可以将输入
/
输出流作为
容器
看待
(
因为输入输出都有
缓冲
区
的概念
)
。因此,任何接受迭代器参数的算法都可以和流一起工作。关于流迭代器的模板形式:
#include <iterator>
template< class T,
class CharT = char,
class Traits = std::char_traits<CharT>,
class Distance = std::ptrdiff_t
> class istream_iterator
: public std::iterator<std::input_iterator_tag, T, Distance, const T*, const T&>;
template< class T,
class CharT = char,
class Traits = std::char_traits<CharT>,
class Distance = std::ptrdiff_t
> class istream_iterator;
template< class T,
class CharT = char,
class Traits = std::char_traits<CharT>
> class ostream_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>;
template< class T,
class CharT = char,
class Traits = std::char_traits<CharT>
> class ostream_iterator;
以及两种流迭代器的构造函数
//输出流迭代器的构造函数
ostream_iterator(ostream_type& stream, const CharT* delim);
ostream_iterator(ostream_type& stream);
//输入流迭代器的构造函数
constexpr istream_iterator();
istream_iterator( istream_type& stream );
istream_iterator( const istream_iterator& other ) = default;
输入输出流迭代器的使用示例:
void test()
{
vector<int> numbers{1, 2, 3, 4, 5};
ostream_iterator<int> osi(cout, "\n");
copy(numbers.begin(), numbers.end(), osi);
}
void test()
{
vector<int> numbers;
istream_iterator<int> isi(cin);
//对于vector插入元素应该调用push_back
//copy(isi, istream_iterator<int>(), numbers.begin());//这样写会有bug,可以思考一下什么原因
copy(isi, istream_iterator<int>(), std::back_inserter(numbers));
copy(numbers.begin(), numbers.end(), ostream_iterator<int>(cout, "\n"));
}
迭代器适配器
back
_
inserter
是函数模板,该函数模板的返回类型是类模板
back
_
insert
_
iterator
,而类模板back
_
i nsert
_
iterator
底层调用了
push
_
back
函数;
front
_
inserter
是函数模板,该函数模板的返回类型是类模板
front
_
insert
_
iterator
,而类模板fron t
_
insert
_
iterator
底层调用了
push
_
front
函数;
inserter
是函数模板,函数模板的返回类型是类模板
insert
_
iterator
,而类模板insert_
iterator
底层调用了
insert
函数。
下面是三个函数模板的接口原型:
template< class Container >
std::back_insert_iterator<Container> back_inserter( Container& c );
template< class Container >
std::front_insert_iterator<Container> front_inserter( Container& c );
template< class Container >
std::insert_iterator<Container>
inserter( Container& c, typename Container::iterator i );
三者对应的可能实现如下:
template< class Container >
std::back_insert_iterator<Container> back_inserter( Container& c )
{
return std::back_insert_iterator<Container>(c);
}
template< class Container >
std::front_insert_iterator<Container> front_inserter( Container& c )
{
return std::front_insert_iterator<Container>(c);
}
template< class Container >
std::insert_iterator<Container>
inserter( Container& c, typename Container::iterator i )
{
return std::insert_iterator<Container>(c, i);
}