C++基础之迭代器
迭代器的分类
插入迭代器(insert iterator):绑定一个容器上后可以向容器中插入元素;
流迭代器(stream iterator):绑定在输入输出流中,可以遍历关联的流;
反向迭代器(reverse iterator):迭代器向后移动,标准库容器中除了forward_list外都有反向迭代器;
移动迭代器(move iterator):使用该迭代器移动其中元素;
插入迭代器(insert iterator)
back_inserter:创建一个使用push_back的迭代器;
front_inserter:创建一个使用push_front的迭代器;
inserter:创建一个使用insert的迭代器;
注意:只有容器支持push_front的情况下,才能使用front_inserter;只有容器支持push_back的情况下,才能使用back_inserter;
若it是inserter生成的插入迭代器,则*it = val;等价于it = c.insert(it,val);++it;
顾名思义back_inserter始终将元素插入到末尾,front_inserter始终将元素插入到头部。
list<int> lst1 = {,,,};
list<int> lst2,lst3;
//复制lst1到lst2,每次将lst1中的元素复制插入到lst2的前面
copy(lst1.cbegin(),lst1.cend(),front_inserter(lst2));
//复制lst1到lst3,每次将lst1中的元素复制插入到lst3的前面
copy(lst1.cbegin(),lst1.cend(),inserter(lst3,lst3.begin()));
流迭代器(stream iterator)
虽然iostream类型不是容器,但是标准库定义用于IO类型对象的迭代器。istream_iterator读取输入流,ostream_iterator向输出流写数据。
istream_iterator操作
可以对任何定义了输入运算符(>>运算符)的类型定义istream_iterator。
从标准输入读取数据存入到数组中:
istream_iterator<int> in_iter(cin);//从cin中读取数据
istream_iterator<int> eof;//尾后迭代器
vector<int> vec(in_iter, eof);//将输入的数据存入数组中
使用算法将输入数据求和:
istream_iterator<int> in_sum(cin), eof;//从cin中读取数据,尾后迭代器
cout << accumulate(in_sum, eof, ) << endl;//将输入的数据存入数组中
istream_iterator允许使用懒惰求值
当我们将istream_iterator绑定到一个流上时,并不保证迭代器立即从流中读取数据;即具体实现中可以推迟从流中读取数据。
标准库保证的是在我们第一次解引用迭代器之前,已经完成从流中读取数据的操作。
ostream_iterator操作
可以对任何定义了输出运算符(<<运算符)的类型定义ostream_iterator。
ostream_iterator<T> out(os);//out将类型为T的值写到输出流os中
ostream_iterator<T> out(os,d);//out将类型为T的值写到输出流os中,每个值后面输出一个C风格的字符串d(一个字符串字面常量或一个指向空字符结尾的字符数组指针)
不允许空的或尾后的ostream_iterator
ostream_iterator<int> out_iter(cout," ");
copy(vec.cbegin(),vec.cend(),out_iter));//输出数组vec中的所有元素,用空格隔开
cout << endl;
反向迭代器(reverse iterator)
反向迭代器(reverse iterator)从容器的尾元素向首元素移动的迭代器,此时递增表示移动到前一个元素,递减表示移动到后一个元素,移动到第一个元素的前一个位置表示结束。
除了forward_list之外的容器都有反向迭代器,可以通过rbegin、rend、crbegin、crend来获得反向迭代器。可以看出,它也有const和非const两个版本。
反向输出数组的所有元素:
vector<int> arr = {,,,,,,,,,};
for(auto riter = arr.crbegin();riter != arr.crend();++riter)
    cout << *riter << endl;
降序排序的另一种写法:
sort(vec.rbegin(),vec.rend());
注意流迭代器不支持递减运算,因为不能在一个流中反向移动。
反向迭代器转换为普通的迭代器
string line = "FIRST,MIDDLE,LAST";
auto pos = find(line.crbegin(), line.crend(), ',');//找到最后一个单词
cout << string(line.crbegin(), pos) << endl;//输出TSAL
cout << string(pos.base(), line.cend()) << endl;//输出LAST
上面通过调用reverse_iterator的base成员函数来完成反向迭代器向普通的迭代器的转换。
注意这两者的转换,关键在于[line.crbegin(), pos)和[pos.base(), line.cend())指向line中相同的元素范围,为了实现这个pos和pos.base()必须指向相邻位置而不是相同位置。
移动迭代器(move iterator)
泛型算法对应的5中迭代器操作
输入迭代器 只读,不写;单遍扫描,只能递增
输出迭代器 只读,不写;单遍扫描,只能递增
向前迭代器 可读写;多遍扫描,只能递增
双向迭代器 可读写;多遍扫描,可递增递减
随机访问迭代器 可读写;多遍扫描,支持迭代器所有运算
C++标准指明了泛型和数值算法的每个迭代器参数的最小类别。
例如find算法要求对序列一遍扫描,对元素只读操作,因此至少需要输入迭代器;replace函数需要一对迭代器,至少是向前迭代器;replace_copy的前两个迭代器至少是向前迭代器,第三个迭代器表示目前位置,必须至少是输出迭代器。
输入迭代器(input iterator)要支持:
它只用于顺序访问,对于输入迭代器,*it++保证有效,但是,递增他可能导致其他指向流的迭代器失效,因此只能用于单遍扫描算法,例如find和accumulate。
- 比较两个迭代器的相等和不相等(==、!=)
- 迭代器的前置和后置递增运算(++)
- 读取元素的解引用运算(*)
- 箭头运算符(->)等价于解引用
输出迭代器(output iterator)要支持:
只能向输出迭代器赋值一次,且它只能用于单遍扫描算法,用作目的位置的迭代器通常是输出迭代器。例如copy的第三个迭代器。
- 迭代器的前置和后置递增运算(++)
- 读取元素的解引用运算(*)
向前迭代器(forward iterator)要支持:
可以读写元素,只能在序列中沿一个方向移动,支持所有输入迭代器和输出迭代器的操作,可以多次读写同一个元素;因此可以保存前向迭代器的状态,可以对序列多次扫描。
双向迭代器(bidirectional iterator)要支持:
可以读写元素,只能在序列中正反两个方向移动,支持所有前向迭代器的操作,还支持前置和后置递减运算符。例如reverse要求双向迭代器。
随机访问迭代器(random-access iterator)
提供在常量时间内访问序列中任意元素,支持双向迭代器的所有功能。
- 比较两个迭代器相对位置的关系运算符(<、>、==、!=、...)
- 迭代器和整数的加减运算符(++、——、+=、—=)
- 两个迭代器减法运算
- 下标运算符,和*等价
C++基础之迭代器的更多相关文章
- (转)python基础之迭代器协议和生成器(一)
		一 递归和迭代 二 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前 ... 
- C++基础之迭代器iterator
		C++基础之迭代器iterator 我们已经知道可以使用下标运算符来访问string对象的字符或vector对象的元素,还有另一种更通用的机制也可以实现同样的目的,这就是迭代器(iterator). ... 
- Day4 - Python基础4 迭代器、装饰器、软件开发规范
		Python之路,Day4 - Python基础4 (new版) 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 ... 
- Python基础之迭代器、生成器
		一.迭代器: 1.迭代:每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值.例如:循环获取容器中的元素. 2.可迭代对象(iterable): 1)定义:具有__ite ... 
- Python 入门基础11 --函数基础4  迭代器、生成器、枚举类型
		今日目录: 1.迭代器 2.可迭代对象 3.迭代器对象 4.for循环迭代器 5.生成器 6.枚举对象 一.迭代器: 循环反馈的容器(集合类型) 每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的 ... 
- python基础之迭代器、生成器、装饰器
		一.列表生成式 a = [0,1,2,3,4,5,6,7,8,9] b = [] for i in a: b.append(i+1) print(b) a = b print(a) --------- ... 
- python基础之迭代器、装饰器、软件开发目录结构规范
		生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大 ... 
- python基础知识---迭代器、生成器、装饰器
		一.迭代器 二.生成器 http://www.cnblogs.com/huxi/archive/2011/07/14/2106863.html def func(): #定义生成器,和普通函数的区别是 ... 
- ES6 基础版迭代器
		ES6中引入了generator function* get() { var result1 = yield c; var result2 = yield b; var result3 = yield ... 
- C++学习基础三——迭代器基础
		迭代器分为两种:一种是iterator,另一种是const_iterator.两者都可进行访问容器中的元素,不同之处是:(1)const_iterator类型只能用于读取容器内的元素,不能更改其值:而 ... 
随机推荐
- C语言的输入
			%*2d%d 去掉前面两位 新旧函数 scanf和scanf_s 去掉安全检查 整型 scanf(“%d”,&x); scanf_s(“%d”,&x); 字符型 char ch; sc ... 
- Xshell登陆服务器及Linux的简单命令
			在之前的推文中,我已经给出了怎样利用Git登陆服务器”你在用xshell,putty登陆?推荐一个小工具(Git)登陆“其中包括xshell登陆服务器.今天讲讲常见的Linux命令,这个和之前将的利用 ... 
- IntelliJ IDEA 从入门到上瘾教程,2019图文版!
			前言:IntelliJ IDEA 如果说IntelliJ IDEA是一款现代化智能开发工具的话,Eclipse则称得上是石器时代的东西了. 其实笔者也是一枚从Eclipse转IDEA的探索者,随着近期 ... 
- 使用flask-restful搭建API
			最简单的例子 ---~~~~ 访问http://127.0.0.1:5000/ , 返回{"hello": "world"} from flask import ... 
- sed命令及替换文件内容
			一.sed (三剑客老二) 1.sed 替换文件内容 sed s###g file 前面两个#中的是原内容,后两个#中的是替换的内容 例:将a.txt文件中的linux替换成java 但是,此时 ... 
- MySQL数据库之表的增删改查
			目录 MySQL数据库之表的增删改查 1 引言 2 创建表 3 删除表 4 修改表 5 查看表 6 复制表 MySQL数据库之表的增删改查 1 引言 1.MySQL数据库中,数据库database就是 ... 
- Node开发知识概括
			一. javascript高级话题(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使 ... 
- codeforces 459 D. Pashmak and Parmida's problem(思维+线段树)
			题目链接:http://codeforces.com/contest/459/problem/D 题意:给出数组a,定义f(l,r,x)为a[]的下标l到r之间,等于x的元素数.i和j符合f(1,i, ... 
- box-sizing(CSS3)
			CSS3新增了盒模型box-sizing,属性值有下面三个: content-box 默认值,让元素维持W3C的标准盒模型.元素的宽度/高度(width/height)= 元素内容框宽度/高度(con ... 
- 微信小程序实现pdf,word等格式文件上传
			目前微信只支持从聊天记录里面获取文件 一.前言 目前微信提供了一个接口 wx.chooseMessageFile 它能让用户从聊天记录里面选择一个或者多个文件,然后返回它的一些信息,列入文件的path ... 
