C++primer -迭代器

除普通的容器迭代器外,标准库还定义了一些迭代器,包含在头文件<iterator>中:

1、插入迭代器

作用:插入迭代器接受一个容器生成一个迭代器,能实现向给定容器添加元素。

对插入迭代器赋值会在插入迭代器所指位置创建赋值的元素的拷贝。

插入迭代器的作用是将赋值改为插入,将泛型算法中的修改变为写入。

以下函数会返回一个插入迭代器:

back_inserter(c) : 接受一个容器的引用c,返回一个与该容器绑定的插入迭代器,该插入迭代器将赋值的拷贝插入到队尾(执行的是push_back)。

inserter(c, p) : 接受一个容器的引用c和迭代器p,返回一个与该容器绑定的插入迭代器,该插入迭代器将赋值的拷贝插入到迭代器所指位置之前(执行的是insert)

front_inserter(c):接受一个容器的引用c,返回一个与该容器绑定的插入迭代器,该插入迭代器将赋值的拷贝插入到队首(执行的是push_front)

插入迭代器支持的操作:

it = t

在it指定位置插入值t。

*it, ++it, it++

不做任何操作,只返回it,存在是为了对齐其他迭代器的使用格式

插入迭代器的常用形式:*it++ = t; 相当于普通迭代器it2的操作: it2 = c.insert(it2, val); ++it2;

2、流迭代器

标准库定义了可以用于IO类型对象的迭代器。

ostream_iterator :向一个输出流写数据

istream_iterator:读取输入流

流迭代器的作用是,我们可以用泛型算法从流对象读取数据以及向其写入数据,流迭代器必须指定迭代器从流中读取的数据的类型。

输入流迭代器支持的操作:

istream_iterator<T> in(is);

创建一个接受T类型值的 绑定到输入流 is 的流迭代器

istream_iterator<T> eof;

默认初始化流迭代器,可以作为一个尾后迭代器

in1 == in2;

in1 != in2;

当in1与in2绑定到相同的输入流时,或二者都是尾后迭代器时,二者相等,否则不等

*in

返回从流中读取的值

in->mem

访问从流中读取的值的成员

++in,in++ 

使用元素类型所对应的>>运算符读取下一个值,前置返回当前的读取,后置返回前一个读取。

以下是一个用istream_iterator从标准输入读取数据,存入一个vector的例子:

istream_iterator<int> int_it(cin); // 创建一个读取int类型数据的输入流迭代器,并绑定到cin流

istream_iterator<int> int_eof;// 默认初始化,不绑定到输入流,表示创建了一个输入流的尾后迭代器。

while(in_iter != eof) vec.push_back(*in_iter++); // 获取从流读取的前一个值。

对于一个绑定到流的迭代器,一旦其关联的流遇到文件尾或遇到IO错误,迭代器的值就与尾后迭代器相等,即,遇到文件尾或IO错误等于对流的遍历结束。

输入流迭代器在泛型算法中的应用:

  • 将输入的内容直接存入容器中:

copy(in_iter, eof, back_inserter(vec));// 将输入内容按空格分隔存入vector<int>类型的容器vec中。

  • 将输入累加:

accumulate(in_iter, eof, 0); // 累加输入内容初值为0

istream_iterator直到使用迭代器时才真正从流中读取。

输出流迭代器:

ostream_iterator支持的操作:

ostream_iterator<T> out(os);

创建一个流迭代器out,绑定到输出流os,out输出的内容类型为T

ostream_iterator<T> out(os, d);

out将类型为T的值写到输出流中,每次输出之后打印一个d, d是一个C风格字符串。

out = val;

调用<<运算符将val存入out绑定的ostream中,相当于os << val; 但规定val的类型为T

*out, ++out, out++

不做任何事,只返回out,只为了对齐迭代器格式。

输出流迭代器应用实例:

ostream_iterator<string> out(cout, " ");

vector<string> vec{"abc", "def", "ghi"};

auto iter = vec.begin();

while(iter != vec.end()){

    *out++ = *iter++; // 相当于:cout << *iter++;

}

3、反向迭代器(forward_list没有反向迭代器)

反向迭代器reverse_iterator就是从尾元素开始向首元素反向移动的迭代器。

可以通过rbegin()\rend()\crbegin()\crend()获取反向迭代器。反向迭代器的rend()是容器首元素之前的一个元素,即首前的位置。对反向迭代器递增得到的是容器中它之前的一个元素。反向迭代器要求容器迭代器支持自减,因此需要双向迭代器权限的容器才支持反向迭代器。

4、移动迭代器

通过调用标准库的make_move_iterator函数,将普通迭代器转换为一个移动迭代器,它接受一个普通迭代器,返回一个移动迭代器。

移动迭代器应用实例:

uninitialized_copy(make_move_iterator(vec.begin()), make_move_iterator(vec.end()), first);// 将vec的元素移动到first指向的原始内存空间。

建议:尽量少地使用移动功能。

迭代器等级

迭代器按可提供的操作分为5个类别:

1、输入迭代器: 只可读入,不能写入,只能递增

可读取序列中的元素

支持的操作:

==、!= ,++,*,->

只能用于顺序访问。

2、输出迭代器: 只写不读,只能递增

支持的操作:

++、*

只能向一个输出迭代器赋值一次,因此输出迭代器是单向的。输出流迭代器是一种输出迭代器。在泛型函数中用作目标迭代器的迭代器 被要求是输出迭代器,比如copy(b1, e1, b2); b2必须至少是一个输出迭代器。

3、前向迭代器 :可以读写元素

只能在序列中沿一个方向移动(通常是只能++不能--),forward_list上的迭代器是一个典型的前向迭代器。

前向迭代器支持所有输入和输出迭代器的操作,且可以多次读写同一个元素。

4、双向迭代器 :可以正向/反向读写序列中的元素。

除了支持所有前向迭代器的操作外,双向迭代器还支持前置和后置递减运算符(--)。

reverse要求双向迭代器。

除了forward_list之外,对于其他容器,标准库都提供符合双向迭代器要求的迭代器。

5、随机访问迭代器

支持双向迭代器的所有操作,且支持随机访问(提供在常量时间内访问序列中任意元素的能力)。

额外支持的操作:

<, <=, >, >=

iter+n, iter+=n, iter-n, iter-=n

iter1-iter2

iter[n]

array、deque、string、vector的迭代器都是随机访问迭代器。

sort要求随机访问迭代器

泛型算法的参数规范:

alg(beg, end, other args); // beg,end是操作序列的迭代器范围, other args是关于算法所需的其他参数

alg(beg, end, dest, other args);

alg(beg, end, beg2, other args);

alg(beg, end, beg2, end2, other args);

以及泛型算法后缀:_if(满足条件则执行操作), _copy(将序列复制到目的序列)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值