目录
迭代器失效
再探迭代器(原书P357)
除了为每个容器定义的迭代器之外,标准库在头文件iterator中还定义了额外几种迭代器。这些迭代器包括以下几种:
1.插入迭代器(insert iterator):这些迭代器被绑定到一个容器上,可以用来向容器插入元素
2.流迭代器(stream iterator):这些迭代器被绑定到输入或输出流上,可用来遍历所有关联的IO流
3.反向迭代器(reverse iterator):这些迭代器向后而不是向前移动,除了forward_list之外的标准库容器都有反向迭代器
4.移动迭代器(move iterator):这些专用的迭代器不是拷贝其中的元素,而是移动它们。
1.插入迭代器
插入迭代器是一种迭代器适配器,它接受一个容器,生成一个迭代器,能实现向给定容器添加元素。当我们通过一个插入迭代器进行赋值时,改迭代器调用容器操作来向给定容器的指定位置插入一个元素,如下表所示:
插入器有三种类型,差异在于元素插入的位置
然后又一些个例子:
这里对于front_inserter还好理解,第二个inserter应该是指直接调用insert把前面这个所有的范围直接插入了迭代器之前的意思吧应该~
2.流迭代器
虽然iostream不是容器,但标准库定义了可以用于这些IO类型对象的迭代器。istream_iterator读取输入流,ostream_iterator向一个输出流写数据。这些迭代器将它们对应的流当作一个特定类型的元素来处理。通过使用迭代器,我们可以用泛型算法从流对象读取数据以及向其写入数据。
istream_iterator操作
当创建一个流迭代器时,必须指定迭代器将要读写的对象类型。一个istream_iterator使用>>来读取流。因此,istream_iterator要读取的类型必须定义了输入运算符。当创建一个istream_iterator时,我们可以将它绑定到一个流。当然,我们还可以默认初始化迭代器,这样就创建了一个可以当作尾后值使用的迭代器。
istream_iterator<int> int_int(cin);//从cin中读取int
istream_iterator<int> int_eof;//尾后迭代器
ifstream in("a_file");
istream_iterator<string> str_it(in);//从"a_file"中读取字符串
下面是一个用istream_iterator从标准输入读取数据,存入一个vector的例子:
istream_iterator<int> in_iter(cin);//从cin中读取int
istream_iterator<int> eof;//istream尾后迭代器
while(in_iter!=eof)
{
vec.push_back(*in_iter++);
}
我们还可以这样写:
istream_iterator<int> in_iter(cin),eof;//从cin中读取int
vector<int> vec(in_iter,eof);//从迭代器范围构造vec
使用算法操作流迭代器
由于算法使用迭代器操作来处理数据,而流迭代器又至少支持某些迭代器操作,因此我们至少可以用某些算法来操作流迭代器。举个栗子:
istream_iterator<int> in(cin),eof;
cout<<accumulate(in,eof,0)<<endl;
懒惰求值没看太懂。。。
ostream_iterator操作
我们可以对任何具有输出运算符(<<运算符)的类型定义ostream_iterator。
我们可以用ostream_iterator来输出值的序列:
ostream_iterator<int> out_iter(cout," ");
for(auto e:vec)
{
*out_iter++=e;
}
cout<<endl;
每一次赋值后,写操作就会提交,并且加上一个空格在后边。
同样可以直接用算法,这比编写循环更加省事:
copy(vec.begin(),vec.end(),out_iter);
cout<<endl;
使用流迭代器处理类类型
3.反向迭代器
注意不可能从一个forward_list或者一个流迭代器创建反向迭代器
举一个应用:
在一个逗号分割的列表中找到第一个元素
auto comma=find(line.cbegin(),line.cend(),",");
cout<<string(line.cbegin(),comma)<<endl;
我们如果求倒数第一个元素
auto rcomma=find(line.rcbegin(),line.rcend(),",");
cout<<string(line.rcbegin(),rcomma)<<endl;
这样其实是错误的,结合反向迭代器的特性我们很容易想到他会输出最后一个元素的逆序输出
我们要用rcomma.base()将其转化为一个正向的迭代器,第二句改成这样就好了:
cout<<string(rcomma.base(),line.end())<<endl;
未完待续~