10-4 再探迭代器

除了为每个容器定义的迭代器之外,标准库在头文件 iterator 中还定义了额外几种迭代器。这些迭代器包括以下几种。

  • 插入迭代器(insert iterator),这些迭代器被绑定到一个容器上,可用来向容器插入元素。
  • 流迭代器( stream iterator):这些迭代器被绑定到输入或输出流上,可用来遍历所关联的IO流。
  • 反向迭代器( reverse iterator ):这些迭代器向后而不是向前移动。除了forward list之外的标准库容器都有反向迭代器。
  • 移动迭代器(move iterator):这些专用的迭代器不是拷贝其中的元素,而是移动它们。我们将在13.6.2节(第480页)介绍移动迭代器。

10.4.1 插入迭代器

插入器是一种迭代器适配器,它接受一个容器,生成一个迭代器,能实现向给定容器添加元素。

当我们通过一个插入迭代器进行赋值时,该迭代器调用容器操作来向给定容器的指定位置插入一个元素。

image-20220223210400731

插入迭代器有三种类型:

  • 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来获得反向迭代器

image-20220223213621942

例子:

逆序打印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;
}

image-20220223220143803

由于[crbegin,rcomma)和[rcomma.base(), cend)所指范围一致

所以rcomma != rcomma.base(),而是出于相邻位置

posted @   咪啪魔女  阅读(34)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示