迭代器类型

辅助函数

本文介绍了STL中的迭代器辅助函数的用法及注意事项,这些迭代器辅助函数包括:begin,end,advance, next (since C++11), prev (since C++11), distance, iter_swap.

这些辅助函数都在名字空间std中,使用他们需要包含以下头文件任意一个:

<iterator>, <array>, <deque>, <forward_list>,
<list>, <map>, <regex>, <set>, <string>,
<unordered_map>, <unordered_set>  <vector>.

advance, next, prev, distance这四个辅助函数使得所有迭代器都拥有类似随机访问迭代器的特性,比如advance(iter, n)可以使得前向迭代器直接向前移动n个位置,类似随机迭代器的iter+n操作。

独立于迭代器类型

这四个辅助函数提供了一层新的抽象层,使得代码可以独立于迭代器的类型。使用这四个辅助函数来操作迭代器可以让我在更改容器类型和迭代器类型的时候不用修改迭代器访问的代码。如果我不使用这几个辅助函数,比如我对一个随机迭代器的操作,写成newPos = pos + 10, 这就要求只有随机迭代器才会通过编译。而若使用newPos = next(pos, 10), 那么就不会有随机迭代器的限制。即使我中途改变了容器和迭代器的类型,也不用修改这段代码。值得一提的是,使用这几个辅助函数并不会造成性能损失,因为其内部会根据迭代器的iterator traits采取不同的策略来移动迭代器,对随机迭代器调用这些函数是一个常量时间的操作,对前向和双向迭代器则和自己手写循环一样,是个线性时间的操作。

不检查范围越界

因为这些函数只接受一个迭代器参数,无法知晓这个迭代器所在容器的信息,也就无法知道是否迭代器到达了begin()之前,或者到了end(), 它只会傻傻的按照你指定的移动次数一直++iter,或者iter+n。而我们知道,对end()进行++操作是未定义的行为。因此使用这些函数的时候,全靠我们调用者自己控制迭代器的合法性。

begin(since C++11)

返回该容器的首元素的迭代器

直接举例:

1
2
3
4
5
6
7
8
#include <iostream>     // std::cout
#include <vector>       // std::vector, std::begin
using namespace std;
int main () {
  vector<int> bar={1,2,3,4,5};
  cout<<*begin(bar)<<endl;        //1
  return 0;
}

end(since C++11)

返回该容器的尾元素的下一位的迭代器

直接举例:

1
2
3
4
5
6
7
8
#include <iostream>     // std::cout
#include <vector>       // std::vector, std::begin
using namespace std;
int main () {
  vector<int> bar={1,2,3,4,5};
  cout<<*end(bar)-1<<endl;        //5
  return 0;
}

advance

void advance(InputIterator &pos, Distance n);

advance没有返回值,它以引用方式来接收并修改pos,使其向前移动n个位置(或者向后, n可以是负数,但此时要保证pos至少是个双向迭代器)。

代码示例:

1
2
3
4
vector<int> a = {1, 2, 3, 4, 5};
auto iter = a.begin();
advance(iter, 3);       //4
advance(iter, -2);        //2

next (since C++11)

ForwardIterator next(ForwardIterator pos, Distance n = 1);

next内部调用了advance(pos, n), 这里pos是传入实参的副本,所以next不会修改实参,它返回对实参副本调用advance(pos, n)后的迭代器位置。

因为它是借助advance来实现其功能,所以上面对advance的使用限制也都适用于它,比如要想往前移动,那么就要需要pos至少是双向迭代器。

vector<int> a = {1, 2, 3, 4, 5};
auto iter = begin(a);
auto niter=next(iter, 3);   //4

prev (since C++11)

BidirectionalIterator prev(BidirectionalIterator pos, Distance n = 1);

prev不修改pos实参的值,它在内部使用一个临时对象pos来调用advance(pos, -n), 返回pos向前移动n个位置后的位置。如果没有第二个参数,默认为1.

prev对参数pos的要求是:至少是一个BidirectionalIterator, 即至少是双向迭代器。

1
2
3
4
vector<int> a = {1, 2, 3, 4, 5};
auto iter = end(a);   //尾元素的下一位
auto s=prev(iter); //5
auto v=prev(iter,2); //4

distance

Distance distance(InputIterator pos1, InputIterator pos2);

Distance的类型是: iterator_traits::difference_type

pos1, pos2必须是同一个容器的迭代器

1
2
3
4
5
vector<int> a = {1, 2, 3, 4, 5};
auto l=begin(a);
auto r = end(a);
int s=distance(l,r); //5
int v=distance(r,l); //-5

参考:

http://blog.csdn.net/elloop/article/details/50410765 http://www.cplusplus.com/