STL源码分析reverse_iterator和inserter

简介

前面介绍了容器适配器stack、queue和函数适配器binder2nd。这篇文章主要介绍迭代器适配器reverse_iterator和inserter。

reverse_iterator

reverse_iterator主要是反转了迭代器。下图是一个简单的示意图。
reverse_iterator
我们看看rbegin()和rend()函数:

1
2
3
4
5
6
7
8
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}

两个函数的关键是reverse_iterator类模板,然后返回的是reverse_iterator。reverse_iterator源代码如下:

1
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
template <class Iterator>
class reverse_iterator
{
protected:
Iterator current;
public:
// 逆向迭代器的5种associated types都和其对应的正向迭代器相同
typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
typedef typename iterator_traits<Iterator>::value_type value_type;
...
typedef Iterator iterator_type; // 代表正向迭代器
typedef reverse_iterator<Iterator> self; // 代表逆向迭代器
public:
explicit reverse_iterator(iterator_type x) : current(x) {}
reverse_iterator(const self & x) : current(x.current) {}
iterator_type base() const {return current; }
reference operator*() const { Iterator tmp = current; return *--tmp; }
// 反向迭代器要先后移一位然后调用原本实现的解引用操作。
pointer operator->() const {return &(*operator()); }
// 成员访问运算符重载调用解引用操作
// 自增自减运算符全部变成相反的操作
self &operator++() { --currten; return *this; }
self &operator--() { ++current; return *this; }
self operator+(difference_type n) const { return self(current - n); }
self operator-(difference_type n) const { return self(current + n); }
}

reverse_iterator(begin()) 和 reverse_iterator(end())分别是使用构造函数生成了reverse_iterator对象,然后进行后面的操作.

inserter

inserter这个迭代器适配器的主要功能是把迭代器表示范围内的元素copy到目标容器中。主要代码:

1
copy(bar.begin(), bar.end(), inserter(foo,it))

下图是一组copy的操作:
inserter
copy的源代码如下:

1
2
3
4
5
6
7
8
9
10
11
template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
while (first != last)
{
//注意赋值操作实际是调用重载操作符,返回一个insert_iterator
*result = *first;
++result; ++first;
}
return result;
}

copy把元素复制到inserter(foo,it)返回的insert_iterator中,然后每次赋值操作都会调用重载的运算符。下面看看inserter源代码:

1
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
template <class Container, class Iterator>
inline insert_iterator<Container>
inserter(Container &x, Iterator i)
{
typedef typename Container::iterator iter;
return insert_iterator<Container>(x, iter(i));
}
template <class Container>
class insert_iterator
{
protected:
Container *container; //底层容器
typename Container::iterator iter;
public:
typedef output_iterator_tag iterator_category;
insert_iterator(Container &x, typename Container::iterator i)
: container(&x), iter(i) {}
insert_iterator<Container> & operator=(const typename Container::value_type &value)
{
// 调用底层容器的insert操作
iter = container->insert(iter, value);
++iter;
return *this;
}
}

在insert_iterator对象中包含两个成员分别是底层容器container和迭代器iter,每次赋值其实就是调用insert操作,因此需要移动迭代器iter指向刚刚创造出的空间。

声明

若有错误,欢迎讨论。严禁抄袭,仅用于学习。

坚持原创技术分享,您的money将鼓励我继续创作!