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指向的是同一段序列,或许下面的图说明的更加清晰一些:
额,这图怎么老消失?
- Object C NSArray (学习笔记三)
- 《C和指针》学习笔记(三)
- c++primer学习笔记(三)
- c++Templates学习笔记(三)
- [C++]C++学习笔记(三)
- C语言程序学习(三)笔记
- 《Effective C++》学习笔记(三)
- C/C++学习笔记(三)
- Objective-c 学习笔记(三)
- C语言学习笔记(三)
- 学习C的一些笔记(三)
- C/C++学习笔记三(函数)
- 《effective c++》学习笔记(三)
- c语言学习笔记三
- C语言学习笔记<三 >
- C/C++学习笔记(三)
- C++Primer学习笔记《三》
- Objective C学习笔记(三)
- Web应用自动化验收工具——Selenium系列预研
- Unity3D图像后处理特效——Sun Shafts
- Main 函数
- UML类图关系大全
- Spring定时程序
- C++学习笔记(三) 迭代器
- 英语词汇5
- JAVA中值类型和引用类型的不同?
- 单链表的数据从小到大排序
- ubuntu9.10 安装openSER 和 利用 RTP proxy 实现TURN,解决 symmetric NAT带给SIP语音无法沟通的困扰
- Unity3D图像后处理特效——Tilt Shift
- 定义类 用到继承的
- 安装Linux分配空间
- VC视图切换技术(视图不销毁)(转)