迭代器深入理解

news2024/10/5 18:31:28

目录

vector 例子引入

迭代器的价值

通过vector和list 迭代器的差异再次深入理解


vector 例子引入

在学习vector底层erase,碰到迭代器失效的时候我有个疑惑,为什么sgi 版(Linux g++使用的)库里实现的迭代器对于有些迭代器失效情况依旧可以使用,而PJ版(VS使用的)库里实现的迭代器无论什么情况都一定会对失效情况报错,检查十分严格。(详情可以参考下面博客)

vector迭代器失效问题_SAKURAjinx的博客-CSDN博客

我当时说了,因为两个版本对迭代器的底层实现不同,sgi 版迭代器是内置类型,是通过typedef 指针的形式创建的。而通过这种形式访问数据,++一次跳过的是4字节(32位平台下,也就是一个指针大小),解引用*也就是直接访问当前位置数据(对于vector来说)。

PJ版实现迭代器不再是内嵌类型,它是封装了迭代器,将它封装成了一个类,内部重载++,* 等运算符。这种方式在访问数据的时候就和指针访问不同。

	    vector<int>::iterator it = v.begin();
		while (it != v.end()) {
			cout << (*it) << " ";
			++it;
		}
		cout << endl;

以上述代码为例,指针的访问方式刚刚说了,

 封装成类,重载运算符访问方式:

 这种方式,*it不是像指针那样单单解引用,而是会去调用重载的函数,it++也是一样调用重载函数,函数内部怎样实现这一过程,解引用、++就返回什么结果。

所以两种方式本质上是不一样的。也正因如此,指针访问检查没有那么严格,有些迭代器失效情况还能继续使用it,而封装重载运算则会经过底层函数的检查,无论什么情况迭代器失效都不会让你再使用或者*it。

迭代器的价值

通过上面的例子我们知道了迭代器的实现方式有不同,并且不同的实现方式带来的结果也有所差异。迭代器真是个十分好用的东西,只能说大佬能设计出这种通用性强功能也强大的组件真的很了不起,一般来说要普通人实现对容器的访问,大概就是string、vector用下标,list、map、set等容器就想不到特别好的方式进行访问了,可能会暴露底层将不应该给程序员展现的节点供其使用,不仅效率低下、暴露底层而且容易使内部节点被误删误改。

迭代器作为六大组件之一,其主要价值就体现在2点:

1、封装性。  将迭代器封装起来使得程序员使用时不会接触到底层,避免了对底层实现的误操作。

复杂的容器底层访问数据的时候是比较复杂的,像set访问数据实际就是搜索树,而我们在外部使用迭代器访问的时候根本不会察觉底层这些麻烦的访问,因为外部都是很统一的形式,仅仅调用迭代器就可以实现。

2、通用适应性。所有容器都能使用迭代器,不像下标访问方式只适合string和vector。

通过vector和list 迭代器的差异再次深入理解

这里vector迭代器指sgi 版本下的实现方式。

1、 对于vector来说,vector<int>:: iterator it = v.begin(); begin()返回的是数组头部的位置,也就是下标为0的位置,end() 则是最后一个下标的后一个位置。

对于list来说,list<int>:: iterator it = st.begin(); begin()返回的是头结点的下一个位置,也就是第一个有效数据的位置。end() 则是哨兵位的头结点。

sgi  vector迭代器就是通过指针遍历,每次走4byte大小,也就是一个数据的位置。

list 迭代器就是通过上一个指针的_next访问下一个指针。

2、

	    vector<int>::iterator it = v.begin();
		while (it != v.end()) {
			cout << (*it) << " ";
			++it;
		}
		cout << endl;

对于迭代器的遍历代码,写的是while(it != v.end()),是否可以写成while(it < v.end()) ?

vector是可以的,但是list 则不行,前面说了list 物理空间不连续,可能后面的节点地址 < 前面节点的地址,因此只能 !=

再从虚拟地址存储的角度来看一下两者的区别:

vector:

 可以看到刚进函数 it 的地址是00 f7 da 20(小端存储,高位存高地址),对应vector对象a的_start地址也是00 f7 da 20,下面 it++,迭代器按指针方式访问,地址+4byte,也就是变为 00 f7 da 24,

来看结果:

 

list:

可以看到刚进函数 it 的地址是00 79 f8 50(小端存储,高位存高地址),对应list对象st的头结点的地址也是00 79 f8 50,下面 it++,st头结点要指向下一个节点的位置,也就是_head->_next->_next,地址是

 

再看此时&it的地址,

小端存储倒着读,也是一样,由此可知,list迭代器的存储方式如我所说就是节点的_next连接,

每次地址不一定跳到哪,可能跳到前面也可能跳到后面。

由地址也可以看出两者访问方式的区别,并且由地址了解迭代器的实现方式后,我们也不用过分觉得迭代器那么神奇,其实过程也就如上面所示。

但迭代器的封装性、通用适应性真的很有价值,容器普遍的访问方式就是迭代器。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

threejs教程(一)

插件安装 npm i three项目引入 这里我随便找的VUE项目练习的 import * as THREE from "three";大致介绍一下threejs的逻辑 一般我们用它是来搭建三维模型的,搭建三维模型就需要的三个要素 场景(scene) 渲染器(renderer) 和相机(camera) 场景简单理解就是唱戏的戏台…

【C++升级之路】第六篇:模板初阶(函数模板类模板)

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;泛型编程的概念&#xff0c;函数模板的概念、格式、原理和基础使用方法&#xff0c;类模板的格式和基础使用…

Java一维数组的定义、赋值和初始化

当数组中每个元素都只带有一个下标时&#xff0c;这种数组就是“一维数组”。一维数组&#xff08;one-dimensional array&#xff09;实质上是一组相同类型数据的线性集合&#xff0c;是数组中最简单的一种数组。 数组是引用数据类型&#xff0c;引用数据类型在使用之前一定要…

Linux操作系统--文本编辑器(保姆级教程)

文本编辑器 Linux是一种文本驱动的操作系统。用户在使用Linux过程中经常需要编辑文本&#xff0c;比如编写脚本文件来执行几条命令行&#xff0c;写电子邮件&#xff0c;创建C语言源程学等&#xff0c;因此&#xff0c;必须熟悉至少一种文本编辑器以便高效地输入和修改文本文件…

Spring循环依赖详解

概述 我们在日常的技术交流中经常会提到Spring循环依赖&#xff0c;听起来挺高大尚的&#xff0c;那Spring到底是如何实现的呢&#xff1f;下面我们就来一一揭秘。 什么是循环依赖 如上图所示&#xff0c;A对象中包含B对象的引用&#xff0c;同时B对象中包含A对象的引用&…

微信小程序自定义tabbar栏【中间突出样式】

文章目录前言一、自定义tabbar栏 配置二、添加自定义tabbar栏组件添加组件代码创建全局字段在组件中保存重要字段三、效果展示总结前言 昨天主管突然给我说微信小程序默认的 tabBar 不美观&#xff0c;让我改成中间突出的那种样式。纵然我心里面有千般不情愿&#xff0c;但还是…

python实现算法与数据结构基础-链表、栈、队列、排序算法、二分查找、二叉树

目录1、算法的概念1.1 举例&#xff1a;1.2 算法的五大特性&#xff1a;1.3 时间复杂度1.4 空间复杂度2、数据结构2.1 内存的存储结构2.2 数据结构的分类2.3 顺序表存储方式3、链表3.1链表实现3.2链表的方法3.3链表增加节点3.4链表删除节点3.5链表总结4、栈4.1 栈的介绍4.2 栈的…

负载均衡SLB和LVS的简单介绍

负载均衡 SLB 阿里云SLB(Server Load Balancing&#xff0c;服务器负载均衡)&#xff1a;是阿里云结合自身弹性计算平台的特点以及强大的技术优势&#xff0c;提供的一套软件负载均衡解决方案&#xff0c;以更好的满足弹性计算平台负载均衡的需求。 什么情况下使用SLB? 简单…

2022尚硅谷SSM框架跟学(四)Spring基础一

2022尚硅谷SSM框架跟学.四 Spring基础一Spring1.Spring简介1.1、Spring概述1.2Spring家族1.3Spring Framework1.3.1Spring Framework特性1.3.2Spring Framework五大功能模块2.IOC2.1.IOC容器2.1.1IOC思想(1).获取资源的传统方式(2).反转控制方式获取资源(3).DI2.1.2、IOC容器在…

(02)Cartographer源码无死角解析-(48) 2D点云扫描匹配→扫描匹配基本原理讲解,代码总体框架梳理

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文末…

项目管理工具dhtmlxGantt甘特图入门教程(八):数据加载(二)

DhtmlxGantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表&#xff0c;可满足应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 这篇文章给大家讲解如何利用dhtmlxGantt加载任务日期。 DhtmlxGantt正版试用下载&#xff08;qun&#xff1a;764148812&#x…

【Linux】进程状态、优先级和进程切换

大家好我是沐曦希&#x1f495; 文章目录一、操作系统进程1.运行队列2.进程状态二、Linux进程状态三、两个特殊进程1.僵尸进程2.孤儿进程四、进程优先级1.优先级概念2.查看系统进程3.PRI和NI4.nice值的更改5.特性五、进程切换1.并发2.进程如何切换一、操作系统进程 什么是进程…

axios拦截器、ElementUI组件的使用

一、axios拦截器 1、axios模块的作用 是对基于http请求的封装。在浏览器对异步请求对象XMLHttpRequest进行封装 2、拦截器 ​ &#xff08;1&#xff09;请求拦截器&#xff1a;对客户端发起的请求进行统一的前期处理&#xff08;token、时间戳、cookie等&#xff09; ​ …

电脑软件经常出现程序未响应是什么原因?及4种解决方法总结

对于电脑小白来说&#xff0c;电脑经常会出现一下莫名其妙的问题&#xff0c;下面我总结的这些方法可以帮大家排除电脑的问题&#xff0c;让电脑速度如飞。资源不足&#xff1a;如果您的电脑资源不足&#xff0c;比如内存或 CPU 使用率过高&#xff0c;那么程序可能会变得不稳定…

【Linux操作系统】多线程(二)

文章目录4. 线程池5. 单例模式5.1 饿汉模式5.2 懒汉模式6. STL、智能指针和线程安全6.1 STL中的容器是否是线程安全的6.2 智能指针是否是线程安全的6.3 其他常见的各种锁7. 读者写者模型7.1 基本概念7.2 读写锁7.3 基本操作7.4 优先级4. 线程池 介绍 一种线程使用模式。线程过…

论文分享 | MnTTS2: 开源的多说话人蒙古语TTS数据集

本次分享内蒙古大学蒙古文信息处理重点实验室、蒙古文智能信息处理技术国家地方联合工程研究中心及语音理解与生成实验室 (S2LAB) 共同发布的开源多说话人蒙古语语音合成数据集及其基线模型。相关论文《MnTTS2: An Open-Source Multi-Speaker Mongolian Text-to-Speech Synthes…

【Java编程进阶】Java异常详解

推荐学习专栏&#xff1a;Java 编程进阶之路【从入门到精通】&#xff0c;从入门到就业精通&#xff0c;买不了吃亏&#xff0c;买不了上当&#xff01;&#xff01; 文章目录1. 异常2. 异常的体系3. Error4. 异常产生的过程5. throw 关键字6. 异常处理6.1 throws 关键字6.2 tr…

基于Node.js和vue的师生互助平台

摘 要随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&am…

Jetpack Compose中的软键盘与焦点控制

FocusRequester 与 FocusManager 在 Compose 中&#xff0c;可以通过 FocusRequester 与 FocusManager 这两个对象可以主动在代码中控制焦点获取和取消焦点&#xff0c;其中FocusRequester可以用来获取焦点&#xff0c;通过调用它的requestFocus()方法来实现&#xff0c;而 Fo…

脚手架搭建Vue项目

以上创建的方式发现一直存在config目录 换种方式 卸载脚手架命令 npm uninstall vue-cli -g 重新安装 npm install vue/cli -g 1.vue create 项目名 2.模板选择&#xff0c;通过键盘上下键来选择&#xff0c;我们选择第三个 自定义 这三个选择分别是 vue2 / vue3 默认模板…