c++stl之反向迭代器用法及注意事项!!!

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++stl之反向迭代器用法及注意事项!!!相关的知识,希望对你有一定的参考价值。

反向迭代器

1.定义:

  • 在容器中从尾元素向首元素反向移动的迭代器

  • 对于反向迭代器,递增和递减的含义会颠倒过来

  • 递增一个反向迭代器会移动到前一个元素

  • 递减一个迭代器会移动到下一个元素

注意:除了forward_list容器之外,其他容器都支持反向迭代器

2.使用反向迭代器的相关函数

  • rbegin() —指向容器尾元素
  • rend()—指向容器首元素之前一个位置
  • crbegin()
  • crend()
  • 下面两个c开头的是反向迭代器的const版本,即不能修改迭代器指向位置的值

3.反向迭代器与正向迭代器的比较
在这里插入图片描述
4.反向迭代器应用之逆序打印数组元素

	vector<int> vec = { 1,2,3,4,5,6 };
	for (auto it = vec.rbegin(); it != vec.rend(); it++)
	{
		cout << *it << " ";
	}

在这里插入图片描述

5.反向迭代器应用之递减序

	vector<int> vec = { 1,2,3,4,5,6 };
	cout << "整理为递减序后,正序打印: " << endl;
	sort(vec.rbegin(), vec.rend());
	for_each(vec.begin(), vec.end(), [](int val) {cout << val << " "; });

在这里插入图片描述
6.反向迭代器需要递减运算符

  • 我们只能从既支持++也支持–的迭代器来定义反向迭代器.
  • 毕竟反向迭代器的目的是在序列中反向移动。
  • 除了forward_list之外,标准容器上的其他迭代器都既支持递增运算,又支持递减运算
  • 但是,流迭代器不支持递减运算,因为不可能在一个流迭代器中反向移动
  • 因此,不可能从一个forward_list或一个流迭代器创建反向迭代器

7.反向迭代器和其他迭代器之间的关系

  • 现在有一个名为line的string容器,里面存放着用逗号分隔的单词表,现在我们需要找到单词表中第一个单词
	string line = "bird,dog,duck,pig";
	auto comma = find(line.begin(), line.end(), ',');
	cout << string(line.begin(), comma) << endl;//这里是一个临时对象

在这里插入图片描述

  • 如果line中有逗号,那么comma指向当前逗号所在位置,否则它将等于line.end().
  • 如果我们希望打印最后一个单词,可以改用反向迭代器
	string line = "bird,dog,duck,pig";
	auto comma = find(line.rbegin(), line.rend(), ',');
	cout << string(line.rbegin(), comma) << endl;//这里是一个临时对象

在这里插入图片描述

  • 当我们试图打印找到的单词时,最有意思的部分就来了,看起来下面的代码是显然的方法:
//错误:将逆序输出单词的字符
cout << string(line.rbegin(), comma) << endl;//这里是一个临时对象
  • 但它会生成错误的输出结果。例如我们输入的是: bird,dog,duck,pig,则这条语句会打印gip

问题所在:

  • 我们使用的是反向迭代器,会方向处理string,因此上述输出语句从crbegin()开始反向打印line的内容。
  • 而我们希望按正常顺序打印从rcomma开始到line末尾间的字符。但是我们不能直接使用rcomma。
  • 因为它是一个反向迭代器,意味着它会朝着string的开始位置移动.
  • 需要做的是,将rcomma转换回一个普通的迭代器,能在line中正向移动.
  • 我们调用reverse_iterator的base成员函数来完成这一转换此成员函数会返回其对应的普通迭代器
	string line = "bird,dog,duck,pig";
	auto rcomma = find(line.crbegin(), line.crend(), ',');
	cout << string(rcomma.base(), line.cend())<< endl;//这里是一个临时对象

在这里插入图片描述

在这里插入图片描述

  • 上图中的对象显示了普通迭代器和反向迭代器之间的关系。
  • 例如,rcomma和rcomma.base()指向不同的元素,line.crbegin()和line.cend()也是如此。
  • 这些不同保证了元素范围无论是正向处理还是反向处理都是相同的。

8.总结:

  • 普通迭代器与反向迭代器的关系反映了左闭合区间的特性。
  • 关键点在于[line.crbegin(),rcomma)和[rcomma.base(),line.cend())指向line中相同的元素范围
  • 为了实现这一点,rcomma和rcomma.base()必须生成相邻位置而不是相同位置,crbegin()和cend()也是如此.

反向迭代器的目的是表示元素范围,而这些范围是不对称的,这导致一个重要的结果:
当我们从一个普通迭代器初始化一个反向迭代器,或是给一个反向迭代器赋值时,结果迭代器与原迭代器指向的并不是相同的元素。

以上是关于c++stl之反向迭代器用法及注意事项!!!的主要内容,如果未能解决你的问题,请参考以下文章

c++stl之lower_bound,upper_bound和equal_range函数的详细介绍!!!

STL之迭代器(iterator)

STL进阶--狡猾的反向迭代器

STL之Array

STL之--插入迭代器(back_inserter,inserter,front_inserter的区别)

STL详解—— 用一棵红黑树同时封装出map和set