面试之快速学习STL-迭代适配器

先放一张大图

参考:http://c.biancheng.net/view/7255.html
在这里插入图片描述

1. 反向迭代器

例子:

    std::list<int> values{1,2,3,4,5};auto start_it = values.rbegin();const auto end_it = values.rend();//start_it end_it std::reverse_iterator<std::list<int>>::iteratorwhile (start_it != end_it) {std::cout << *start_it << std::endl;++start_it;}/*54321*/
  1. 想使用反向迭代器实现逆序遍历容器,则该容器的迭代器类型必须是双向迭代器或者随机访问迭代器。
    在这里插入图片描述
  2. 常见操作
    在这里插入图片描述
    std::vector<int> values{1,2,3,4,5};auto r_start_it = values.rbegin();const auto end_it = values.rend();//r_start_it end_it std::reverse_iterator<std::list<int>>::iteratorwhile (r_start_it != end_it) {std::cout << *r_start_it << std::endl;++r_start_it;}/*54321*/r_start_it = values.rbegin();std::cout << "r_start_it + 3 = " << *(r_start_it + 3)<< std::endl;std::cout << "r_start_it[3] = " << r_start_it[3] << std::endl;
  1. 注意这里不能用std::list,因为它是双向迭代器, +3的操作需要随机访问迭代器。故联想到std::list排序只能使用list提供的 sort 接口,而不能使用algorithm 提供的 sort 接口,因为链表的物理地址不连续,迭代器为双向迭代器,不支持 + - 操作,而算法库中的 sort 接口需要支撑 + - 的随机迭代器;

2. 插入迭代器适配器

在这里插入图片描述

感觉没啥好讲的,看看代码:

#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main() {//创建一个 vector 容器std::vector<int> foo;//创建一个可向 foo 容器尾部添加新元素的迭代器std::back_insert_iterator< std::vector<int> > back_it(foo);//将 5 插入到 foo 的末尾back_it = 5;//将 4 插入到当前 foo 的末尾back_it = 4;//将 3 插入到当前 foo 的末尾back_it = 3;//将 6 插入到当前 foo 的末尾back_it = 6;//输出 foo 容器中的元素for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it)std::cout << *it << ' ';return 0;/*5 4 3 6*/
}
  1. 每次插入新元素时,该元素都会插入到当前 foo 容器的末尾。换句话说,程序中 11-17 行的每个赋值语句,都可以分解为以下这 2 行代码:

//pos表示指向容器尾部的迭代器,value 表示要插入的元素
pos = foo.insert(pos,value);
++pos;

3. istream_iterator和ostream_iterator

原理源码:原理

  1. 自己理解:istream_iterator是重载了++操作符然后调用的是read(); ostream_iterator重载 = 操作符,做输出操作
#include <iostream>
#include <thread>
#include <vector>
#include <numeric>
#include <algorithm>
#include <cstring>
#include <deque>
#include <iterator>
using namespace std;int main()
{deque<int> id;istream_iterator<int> intie(cin),eos;                     //开始触发一次输入   copy(intie, eos, inserter(id, id.begin()));               //迭代器类型为InputIterator,所以这里调用copy的时候采用*result = *first;版本,会使用重载类型 ,那么就会转换为插入操作      //其中++first会继续调用下一个,然后重载为新的输入ostream_iterator<int> outie(cout, " ");                  //deque的迭代器类型为random_access_iterator,也会是 *result = *first;调用赋值操作  result++操作,返回本身,不影响后面的输出操作copy(id.begin(), id.end(), outie);                       //将=操作,转换为输出操作cout << endl;system("pause");
}

3. 移动迭代器

std::vector<std::string> v1{ "haha", "xixi" };//调用移动构造函数std::vector<std::string> v2(make_move_iterator(v1.begin()), make_move_iterator(v1.end()));std::cout << "v1 : " << std::endl;for (auto record : v1)std::cout << record << std::endl;std::cout << "v2 : " << std::endl;for (auto record : v2)std::cout << record << std::endl;/*v1 :v2 : hahaxixi*/

没啥好说的,就是每个值调用移动构造函数make_move_iterator

4. advance()函数用法详解

template <class InputIterator, class Distance>
void advance (InputIterator& it, Distance n);

  1. 根据 it 类型是否为随机访问迭代器,advance() 函数底层采用了不同的实现机制:
    当 it 为随机访问迭代器时,由于该类型迭代器支持 p+n 或者 p-n(其中 p 就是一个随机访问迭代器)运算,advance() 函数底层采用的就是 it+n 操作实现的;
    当 it 为其他类型迭代器时,它们仅支持进行 ++ 或者 – 运算,这种情况下,advance() 函数底层是通过重复执行 n 个 ++ 或者 – 操作实现的。

#include <iostream>     // std::cout
#include <iterator>     // std::advance
#include <forward_list>
using namespace std;
int main() {//创建一个 forward_list 容器forward_list<int> mylist{1,2,3,4};//it为前向迭代器,其指向 mylist 容器中第一个元素forward_list<int>::iterator it = mylist.begin();//借助 advance() 函数将 it 迭代器前进 2 个位置advance(it, 2);cout << "*it = " << *it;return 0;
}

注意: 此程序中,由于 it 为前向迭代器,其只能进行 ++ 操作,即只能前进(右移),所以 advance() 函数的第 2 个参数只能为正数。

5. distance()函数用法详解

template
typename iterator_traits::difference_type distance (InputIterator first, InputIterator last);

  1. first 和 last 的迭代器类型,直接决定了 distance() 函数底层的实现机制:
    当 first 和 last 为随机访问迭代器时,distance() 底层直接采用 last - first 求得 [first, last) 范围内包含元素的个数,其时间复杂度为O(1)常数阶;
    当 first 和 last 为非随机访问迭代器时,**distance() 底层通过不断执行 ++first(或者 first++)直到 first==last,**由此来获取 [first, last) 范围内包含元素的个数,其时间复杂度为O(n)线性阶。
#include <iostream>     // std::cout
#include <iterator>     // std::distance
#include <list>         // std::list
using namespace std;int main() {//创建一个空 list 容器list<int> mylist;//向空 list 容器中添加元素 0~9for (int i = 0; i < 10; i++) {mylist.push_back(i);}//指定 2 个双向迭代器,用于执行某个区间list<int>::iterator first = mylist.begin();//指向元素 0list<int>::iterator last = mylist.end();//指向元素 9 之后的位置//获取 [first,last) 范围内包含元素的个数cout << "distance() = " << distance(first, last);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/84669.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL - 开窗(窗口)函数

什么是开窗函数&#xff1f; 开窗函数对一组值进行操作&#xff0c;它不像普通聚合函数那样需要使用GROUP BY子句对数据进行分组&#xff0c;能够在同一行中同时返回基础行的列和聚合列 开窗函数的语法形式为&#xff1a;函数 over(partition by <分组用列> order by …

用Python画出极坐标的基向量

文章目录 极坐标基向量的推导可视化 极坐标基向量的推导 极坐标其实很神奇&#xff0c;一方面&#xff0c;它描述的是平直时空&#xff0c;另一方面&#xff0c;任意两点间的坐标差为 d r , d θ \text dr, \text d\theta dr,dθ时&#xff0c;两点间的距离却是不固定的。极坐…

Leetcode刷题之1658. 将 x 减到 0 的最小操作数

题目: 算法分析: 可以看出,这道题本意是从计算两侧和为x 的数字, 要求数量最少, 那我们可以反向思考, 假如整个数组的和为sum, 那么我们就可以求中间部分和为sum-x的数字(当然必须连续), 当中间部分的数字同时达到和为sum-x以及长度最长两个要求时, 两侧数字也就达到了和为x以…

嵌入式设备应用开发(发现需求和提升价值)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 很多做技术的同学,都会陷入到技术的窠臼之中。对于如何做具体的产品、实现具体的技术,他们可能很感兴趣。但是做出来的东西做什么用,或者说是有没有竞争力,事实上他们不是很关心…

#systemverilog# 之 event region 和 timeslot 仿真调度(六)疑惑寄存器采样吗

一 象征性啰嗦 想必大家在刚开始尝试写Verilig HDL代码的时候,都是参考一些列参考代码,有些来自于参考书,有些来自于网上大牛的笔记,甚至有写来自于某宝FPGA开发板的授权代码。我还记得自己当时第一次写代码,参考的是一款Altera 芯片,结合Quartus 开发软件, 在上面练习…

CFC编程入门_【10分钟学会】

什么是CFC&#xff1a; 【差不多10分钟全学会】 CFC是图形化编程&#xff0c; 跟单片机的连线一样&#xff0c; 唯一的区别&#xff1a;功能块右侧是【只能输出】引脚。 只有左侧引脚可以输入输出。 有哪些控件&#xff1a; 指针&#xff1a;用于拖动功能块。 控制点&#xf…

opencv进阶14-Harris角点检测-cv2.cornerHarris

类似于人的眼睛和大脑&#xff0c;OpenCV可以检测图像的主要特征并将这 些特征提取到所谓的图像描述符中。然后&#xff0c;可以将这些特征作为数据 库&#xff0c;支持基于图像的搜索。此外&#xff0c;我们可以使用关键点将图像拼接起 来&#xff0c;组成更大的图像。&#x…

抖音web主页视频爬虫

需要抖音主页视频爬虫源码的发私信&#xff0c;小偿即可获得长期有效的采集程序。 比构造 s_v_web_id 验证滑块的方法更快&#xff0c;更稳定。

【HSPCIE仿真】输入网表文件(1)基本内容和基本规则

输入网表文件 1. 输入网表文件基本内容2. 输入网表文件示例3. 一些基本规则4. 数值表示5. 压缩文件格式的读取6. 参数和表达式 从HSPICE的仿真流程看&#xff0c;出去初始化配置过程&#xff0c;真正的仿真是从输入网表文件开始的。 HSPICE 根据输入网表文件&#xff08; inpu…

iconfont 图标在vue里的使用

刚好项目需要使用一个iconfont的图标&#xff0c;所以记录一下这个过程 1、iconfont-阿里巴巴矢量图标库 这个注册一个账号&#xff0c;以便后续使用下载代码时需要 2、寻找自己需要的图标 我主要是找两个图标 &#xff0c;一个加号&#xff0c;一个减号&#xff0c;分别加入到…

【C++】容器适配器stack、queue以及deque容器

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录 前言一、什么是容器适配器1.1 stack的…

[Linux]文件IO

文章目录 1. 文件描述符1.1 虚拟地址空间1.1.1 存在的意义1.1.2 分区 1.2 文件描述符1.2.1 文件描述符1.2.2 文件描述符表 2. Linux系统文件IO2.1 open/close2.1.1 函数原型2.1.2 close函数原型2.1.3 打开已存在文件2.1.4 创建新文件2.1.5 文件状态判断 2.2 read/write2.2.1 re…