1、三种迭代器
1)插入迭代器(insert iterator):迭代器适配器,与容器绑定在一起,实现在容器中插入元素的功能。形参为一个迭代器和一个指向容器的引用。
• back_inserter,创建使用 push_back 实现插入的迭代器,形参为指向容器的引用的迭代器适配器。
• front_inserter,使用 push_front 实现插入。
• inserter,使用 insert 实现插入操作。除了所关联的容器外,inserter还带有第二实参:指向插入起始位置的迭代器。Inserter在它的迭代器实参所指的位置前面插入新元素。
replace_copy (ivec.begin(), ivec.end(), inserter (ilst, it), 100, 0);
2)iostream迭代器(iostream iterator):与输入或输出流绑定在一起,用于迭代遍历所关联的 IO 流。
虽然 iostream 类型不是容器,但标准库同样提供了在 iostream 对象上使用的迭代器:istream_iterator 用于读取输入流,而 ostream_iterator 则用于写输出流。这些迭代器将它们所对应的流视为特定类型的元素序列。使用流迭代器时,可以用泛型算法从流对象中读数据(或将数据写到流对象中)。
iostream迭代器的构造函数 |
||
istream_iterator<T> in(strm); |
创建从输入流strm中读取T类型对象的istream_iterator对象 |
|
istream_iterator<T> in; |
istream_iterator 对象的超出末端迭代器 |
|
ostream_iterator<T> in(strm); |
创建将T类型的对象写到输出流strm的ostream_iterator对象 |
|
ostream_iterator<T> in(strm, delim); |
创建将 T 类型的对象写到输出流 strm 的ostream_iterator 对象,在写入过程中使用 delim作为元素的分隔符。delim 是以空字符结束的字符数组(C风格字符串)。 |
|
istream_iterator 的操作 |
||
it1 == it2 it1 != it2 |
比较两上 istream_iterator 对象是否相等(不等)。迭代器读取的必须是相同的类型。如果两个迭代器都是 end 值,则它们相等。对于两个都不指向流结束位置的迭代器,如果它们使用同一个输入流构造,则它们也相等 |
|
*it |
返回从流中读取的值 |
|
it->mem |
是 (*it).mem 的同义词。返回从流中读取的对象的 mem 成员 |
|
++it it++ |
通过使用元素类型提供的 >> 操作从输入流中读取下一个元素值,使迭代器向前移动。通常,前缀版本使用迭代器在流中向前移动,并返回对加 1 后的迭代器的引用。而后缀版本使迭代器在流中向前移动后,返回原值 |
(1)流迭代器都是类模板:任何已定义输入操作符(>> 操作符)的类型都可以定义istream_iterator。任何已定义输出操作符(<< 操作符)的类型可定义ostream_iterator。
(2)示例
示例1
#include "map"
#include "set"
#include "vector"
#include "string"
#include "fstream"
#include "iostream"
#include "sstream"
#include "iterator"
using namespace std;
int main(int argc, char **argv)
{
istream_iterator<int> cin_it(cin);
istream_iterator<int> end_of_stream;
vector<int> vec;
while (cin_it != end_of_stream)
{
vec.push_back(*cin_it++);
}
//also could be written like this
//istream_iterator<int> cin_it(cin);
//istream_iterator<int> end_of_stream;
//vector<int> vec(cin_it, end_of_stream);
return 0;
}
其中end_of_stream定义为空的迭代器对象,用作结束迭代器。绑定流上的迭代器在遇到文件结束或某个错误时,将等于结束迭代器的值。
示例2
#include "map" #include "set" #include "vector" #include "string" #include "fstream" #include "iostream" #include "sstream" #include "iterator" using namespace std; int main(int argc, char **argv) { ostream_iterator<string> out_iter(cout, "\n"); istream_iterator<string> in_iter(cin), EndOfStream; while(EndOfStream != in_iter) { *out_iter++ = *in_iter++; } return 0; }
先iter++,返回iter,再*iter。
示例3
#include "map" #include "set" #include "vector" #include "string" #include "fstream" #include "iostream" #include "sstream" #include "iterator" #include "algorithm" using namespace std; int main(int argc, char **argv) { ifstream infile("C:\\1.txt"); istream_iterator<int> cin_it(infile); istream_iterator<int> EndOfStream; vector<int> vec(cin_it, EndOfStream); sort(vec.begin(), vec.end()); ostream_iterator<int> output(cout, " "); unique_copy(vec.begin(), vec.end(), output); return 0; }
(3)流迭代器的限制
• 不可能从 ostream_iterator 对象读入,也不可能写到istream_iterator 对象中。
• 一旦给 ostream_iterator 对象赋了一个值,写入就提交了。赋值后,没有办法再改变这个值。此外,ostream_iterator 对象中每个不同的值都只能正好输出一次。
• ostream_iterator 没有 -> 操作符。
3)反向迭代器(reverse iteraor):反向遍历。所有容器类型都定义了自己的reverse_iterator类型,由 rbegin 和 rend 成员函数返回。
反向迭代器需要使用自减操作符。流迭代器不能创建反向迭代器(因为不能反向遍历流)。
示例
int main(int argc, char **argv) { string::iterator comma = find(line.begin(), line.end(), ','); cout << string(line.begin(), comma) << endl; return 0; }
2、map、set和list类型提供双向迭代器,而string、vector和deque容器上定义的迭代器都是随机访问迭代器都是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。
3、迭代器
Input iterator(输入迭代器) |
读,不能写;只支持自增运算 |
Output iterator(输出迭代器) |
写,不能读;只支持自增运算 |
Forward iterator(前向迭代器) |
读和写;只支持自增运算 |
Bidirectional iterator(双向迭代器) |
读和写;支持自增和自减运算 |
Random access iterator(随机访问迭代器) |
读和写;支持完整的迭代器算术运算 |
4、关联容器的key是const对象,所以只能使用与关联容器绑在一起的迭代器来提供用于读操作的实参。最好将关联容器上的迭代器视为支持自减运算的输入迭代器,而不是完整的双向迭代器。
5、超出末端迭代器用作结束遍历的“哨兵”,指向范围内最后一个元素的下一位置。超出末端迭代器可能指向不存在的元素,因此永远不能做解引用运算。
6、随机迭代器,除了支持双向迭代器相同的操作之外,还提供了使用关系运算比较迭代器值的能力,以及在迭代器上做算术运算的能力。因此,这类迭代器支持随机访问元素。
参考:
[1] http://blog.163.com/zhoumhan_0351/blog/static/39954227201031652936970/
[2] http://blog.163.com/zhoumhan_0351/blog/static/39954227201022644534780/
[3] 迭代器
http://blog.163.com/zhoumhan_0351/blog/static/39954227201022783524890/
[4] http://blog.163.com/zhoumhan_0351/blog/static/3995422720103174417603/