14、C++ Primer 4th 笔记,迭代器-阿里云开发者社区

开发者社区> hopegrace> 正文

14、C++ Primer 4th 笔记,迭代器

简介: 1、三种迭代器 1)插入迭代器(insert iterator):迭代器适配器,与容器绑定在一起,实现在容器中插入元素的功能。形参为一个迭代器和一个指向容器的引用。 • back_inserter,创建使用 push_back 实现插入的迭代器,形参为指向容器的引用的迭代器适配器。
+关注继续查看

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);

2iostream迭代器(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类型的对象写到输出流strmostream_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;
}

wps_clip_image-18785

2mapsetlist类型提供双向迭代器,而stringvectordeque容器上定义的迭代器都是随机访问迭代器都是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。

3、迭代器

Input iterator(输入迭代器)

读,不能写;只支持自增运算

Output iterator(输出迭代器)

写,不能读;只支持自增运算

Forward iterator(前向迭代器)

读和写;只支持自增运算

Bidirectional iterator(双向迭代器)

 读和写;支持自增和自减运算

Random access iterator(随机访问迭代器)

读和写;支持完整的迭代器算术运

4、关联容器的keyconst对象,所以只能使用与关联容器绑在一起的迭代器来提供用于读操作的实参。最好将关联容器上的迭代器视为支持自减运算的输入迭代器,而不是完整的双向迭代器。

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/

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
《C Primer Plus》读书笔记——递归
递归的原理 一个函数调用其本身,此调用过程为递归(recursion)。 递归的使用 举个栗子: /*用来测试UpAndDown函数的驱动程序*/ #include void UpAndDown (int); int main(void) { UpAnd...
925 0
《C Primer Plus》读书笔记——数组和指针(1)
背景 此章笔记以读者有简单的C语言基础,对数组(array)、指针(pointer)有初步了解及应用,想扎实基础或深入探究为背景而写。 数组的使用 举个栗子: /*打印每月的天数(每四年错一次)*/ #include #define MONTHS 12 ...
905 0
32、C++ Primer 4th 笔记,多重继承与虚函数
1、只有在定义之后,类才可以用作多重继承的基类。按照基类构造函数在派生列表中的出现次序调用。 2、多重继承中,派生类的指针或引用可以转换为任意基类的指针或引用。 3、当一个类继承于多个基类的时候,那些基类之间没有隐含的关系,不允许使用一个基类的指针访问其它基类的成员。
628 0
38、C++ Primer 4th笔记,特殊工具与技术,嵌套类
1、在一个类内部再定义另外一个类,这样的类称为嵌套类(nested class),也称为嵌套类型(nested type)。嵌套类最常用于执行类。 嵌套类是独立的类,基本上与它们的外围类不相关,因此,外围类和嵌套类的对象是互相独立的。
649 0
41、C++ Primer 4th笔记,IO库,格式化IO操作
1、除了条件状态之外,每个iostream对象还维持一个控制IO格式化细节的状态。如整形值的基数,浮点值的精度,输出元素的宽度等。标准库还定义了一组操纵符来修改对象的格式状态。操纵符(manipulator)是可用作输入或输出运算符的操作数,它是一个函数或对象(a manipulator is a function or object that can be used as an operand([计]操作数;运算对象) to an input or output operator(运算符).)。
802 0
39、C++ Primer 4th笔记,特殊工具与技术,联合(union)
1、联合(union)是一种特殊的类。一个union对象可以有多个数据成员,但是任何时刻,只有一个成员可以有值。当将一个值赋给union对象的一个成员的时候,其他所有成员都变为未定义的。每个 union 对象的大小在编译时是固定的:至少与最大数据成员的一样大。
724 0
javascript中的迭代器
1.forEach迭代器 forEach方法接收一个函数作为参数,对数组中每个元素使用这个函数,只调用这个函数,数组本身没有任何变化 //forEach迭代器 function square(num){ document.
726 0
+关注
698
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载