C++学习笔记(三) 迭代器

来源:互联网 发布:勒布朗詹姆斯数据 编辑:程序博客网 时间:2024/06/05 03:10

迭代器

迭代器用于存取一个序列中的元素,其用法类似于指针(实际上迭代器就可以看做是泛化的指针)。不同的是,迭代器比指针更为抽象,它可以指向容器中的一个位置,而我们不必关心这个位置对应的真正物理地址。

iterator从操作方法分可分为如下5类:

Input iterator

Read, but not write; increment only

Output iterator

Write, but not read; increment only

Forward iterator

Read and write; increment only

Bidirectional iterator

Read and write; increment and decrement

Random access iterator

Read and write; full iterator arithmetic


下面的concept继承关系图可以更清楚的说明这5类之间的关系,越下面的迭代器,使用越灵活,操作方法也越多。


对于Input Iterator和output iterator,常用的实例就是流迭代器,分别是:istream_iterator和ostream_iterator。它们的构造函数如下:

istream_iterator<T> in(strm);

Create istream_iterator that reads objects

of type T from input stream strm .

istream_iterator<T> in;

Off-the-end iterator for istream_iterator .

ostream_iterator<T> in(strm);

Create ostream_iterator that writes objects

of type T to the output stream strm .

ostream_iterator<T> in(strm, delim);

Create ostream_iterator that writes objects

of type T to the output stream strm using

delim as a separator between elements.

delim is a null-terminated character array.

对于两个输入流迭代器,要进行相等性比较必须具有同样的类型。如果它们都指向流结束,那么它们相等,如果它们都没有指向流结束,那么它们只要指向同一个流就相等,这个特性常常被用在判断流结束上。下面是使用输入流迭代器的一个例子:

istream_iterator<int> in_iter(cin); // read ints from cinistream_iterator<int> eof; // istream "end" iteratorvector<int> vec(in_iter, eof); // construct vec from an iterator range

向前迭代器没有输入输出迭代器的对于自增操作和写入(或读取)操作必须交替进行的限制,它可以自由的进行读写操作,不过只能自增,不能自减。

双向迭代器比向前迭代器更灵活,它在其基础上加入了自减的操作。向map,set,list这些容器提供的都是双向迭代器。

随机访问迭代器从名字上就可以看出来,它支持对容器的随机访问等操作,在双向迭代器的基础上,它还支持p+=n,p-=n,p+n,p-n,p1-p2,p1 or p2等操作。对于像string,vector,deque这些容器提供的都是随机访问迭代器,可以看出这些容器都是采用连续数据结构的。

以上对迭代器的划分是按照他们的concept分类进行划分的,实际上,我们还可以从它的使用角度上进行划分,例如逆向迭代器。通过container.rbegin(),container.rend()这两个容器函数可以得到容器的逆向迭代器,它的操作方式和普通的迭代器正好相反,我们可以用它们对容器进行逆向迭代。

使用逆向迭代器一定要注意它真正指向的元素,请看下面这个例子,假设有这么一个字符串line:

FIRST,MIDDLE,LAST

现在要打印出最后一个单词,我们可能会如此写C++代码:

string::reverse_iterator rcomma = find(line.rbegin(), line.rend(), ',');cout << string(line.rbegin(), rcomma) << endl;

但打印结果却是:TSAL

仔细想想,这个结果是很正常的,因为逆向迭代器本来就是对容器的逆向迭代。但这可不是我们想要的,要想得到last这个打印结果,我们需要如下修改代码:

cout << string(rcomma.base(), line.end()) << endl;

调用逆向迭代器的base函数可以得到对应的正向迭代器,有些童鞋看到这里可能会对其迭代范围感到疑惑,因为它并没有打印出逗号,实际上rcoma和rcoma.base()并没有指向同一个元素,STL这样设计的原因主要是考虑到序列的左闭右开原则,使得rcomma.base(), line.end()和line.rbegin(), rcomma指向的是同一段序列,或许下面的图说明的更加清晰一些:



额,这图怎么老消失?



原创粉丝点击