10-4 再探迭代器
除了为每个容器定义的迭代器之外,标准库在头文件 iterator 中还定义了额外几种迭代器。这些迭代器包括以下几种。
- 插入迭代器(insert iterator),这些迭代器被绑定到一个容器上,可用来向容器插入元素。
- 流迭代器( stream iterator):这些迭代器被绑定到输入或输出流上,可用来遍历所关联的IO流。
- 反向迭代器( reverse iterator ):这些迭代器向后而不是向前移动。除了forward list之外的标准库容器都有反向迭代器。
- 移动迭代器(move iterator):这些专用的迭代器不是拷贝其中的元素,而是移动它们。我们将在13.6.2节(第480页)介绍移动迭代器。
10.4.1 插入迭代器
插入器是一种迭代器适配器,它接受一个容器,生成一个迭代器,能实现向给定容器添加元素。
当我们通过一个插入迭代器进行赋值时,该迭代器调用容器操作来向给定容器的指定位置插入一个元素。
插入迭代器有三种类型:
back_inserter
:创建一个使用push_back的迭代器。front_inserter
:创建一个使用push_front的迭代器。inserter
:创建一个使用insert的迭代器。此函数接受第二个参数,这个参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器所表示的元素之前。
前二者接受容器类型,返回指向对应容器的插入迭代器
inserter接受容器类型和一个指向该容器的迭代器,把该迭代器转换为插入迭代器
只有在容器支持push_front的情况下,我们才可以使用front_inserter,类似的,只有在容器支持 push_back的情况下,我们才能使用back_inserter。
例子#
insterter插入迭代器举例
vector<int> vi;
auto it = inserter(vi, vi.begin());
*it = 0;
//等价于:
auto it = vi.begin();
it = vi.insert(it, 42); //it指向新的元素
++it; //递增it使它指向原来的元素
list<int> lst = {1,2,3,4};
list<int> lst2, lst3;
//lst2 : 1,2,3,4
copy(lst.cbegin(), lst.cend(), inserter(lst2, lst2.begin()));
//lst3 : 4,3,2,1
copy(lst.cbegin(), lst.cend(), front_inserter(lst3));
10.4.2 iostream迭代器:略
10.4.3 反向迭代器
基本介绍#
反向迭代器就是在容器中从尾元素向首元素反向移动的迭代器。
对于反向迭代器,递增(以及递减)操作的含义会颠倒过来。
递增一个反向迭代器(++it)会移动到前一个元素;递减一个迭代器(--it)会移动到下一个元素。
除了forward_list外都具有反向迭代器
通过rbegin,rend,rcbegin,rcend来获得反向迭代器
例子:
逆序打印vector:
vector<int> v = {0,1,2,3,4};
for(auto r_iter = v.crbegin();
r_iter != v.crend();
++r_iter)
cout<<*r_iter<<" ";
//输出:4 3 2 1 0
逆序排序:
sort(v.begin(), v.end()); //顺序排序
sort(v.rbegin(), v.rend()); //逆序排序
反向迭代器需要递减运算符#
不必惊讶,我们只能从既支持++也支持---的迭代器来定义反向迭代器。
毕竟反向迭代器的目的是在序列中反向移动。除了forward_list之外,标准容器上的其他迭代器都既支持递增运算又支持递减运算。
但是,流迭代器不支持递减运算,因为不可能在一个流中反向移动。因此,不可能从一个forward_list或一个流迭代器创建反向迭代器。
反向迭代器和其他迭器的关系#
考虑一个例子:输出一个逗号分隔的string列表的最后一个string
//在逗号分隔的列表中查找第一个元素
auto comma = find(line.cbegin(), line.cend(), ',');
//在逗号分隔的列表中查找最后一个元素
auto comma = find(line.crbegin(), line.crend(), ',');
输出时要将反向迭代器转换为普通迭代器,因为反向迭代器会反向处理string
int main(){
string line = "hello,world,NiHao";
auto rcomma = find(line.crbegin(), line.crend(), ',');
//输出:oaHiN 【反向的NiHao】
cout<<string(line.crbegin(), rcomma)<<endl;
//输出:NiHao
cout<<string(rcomma.base(), line.cend())<<endl;
return 0;
}
由于[crbegin,rcomma)和[rcomma.base(), cend)所指范围一致
所以rcomma != rcomma.base(),而是出于相邻位置
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!