list的底层:

我们之前讲解了list,今天我们来看一下list的底层:

list底层是一个双向带头循环的链表,之前我们学习数据结构的时候,我们就学过。

迭代器的封装:

我们看这个图片,我们的链表的指针可以达到链表的迭代器能力吗?

达不到的,只有在数组里面,连续地数据的时候,指针才可以是看作迭代器。

迭代的两个核心的能力就是:++和*。

在链表里面,数据是不连续的,对于迭代器的++,是实现不了的,得不到下一个数据的位置。*解引用的话,得到的也是这个节点,得不到里面的数据,这就和数组里面的迭代器是不一样的。

在数组里面,数据是连续的,我们的迭代器++就可以到下一数据的个位置。*解引用就可以直接得到这个数据的。

但是:

我们在list里面我们是可以使用迭代器完成++和*的操作的,那么底层是怎么实现我们的迭代器的呢?

我们看一下我们的库里面是怎么干的。

我们的底层使用一个自定义的类来把我们的指针封装起来;

我们使用封装来实现我们的迭代器的功能:

对于我们的迭代器的++和解引用*,我们可以直接使用函数重载来实现,我们直接实现在类里面。

这个类就是我们的迭代器,我们给类的名字就叫做list_iterator;

insert的底层:

我们看这个insert的底层:

我们看insert,我们的插入是把数据插入到,迭代器position位置的前面。

我们看这个代码,我们是申请到介蒂安以后,我们的tmp的next指向position.node;

在这里可能会有疑惑,为什么是.,这个不应该是类,结构体调用里面的成员才使用的吗?

是的:

我们在封装我们的指针的时候,我们把我们的node结点也给封装进去了,因为我们的后面要实现函数的重载,我们要调用node。

我们说我们的string和vector的迭代器使用的就是我们的原生指针,list使用的迭代器就是把我们的指针进行封装,在内部实现函数重载,但是string和vector也不一定是要使用原生指针,也可以封装他们的指针来进行。

list的底层的实现:

迭代器的实现:

我们把我们的结点的指针封装到我们的类里面,这个类就是我们的list的迭代器。

然后我们在这个类里面,我们实现迭代器的++,*解引用等一些列的操作。

迭代器失效:

我们之前讲解vector的时候,我们的insert函数和erase函数都发生了迭代器失效的问题,我们的插入函数失效的原因是我们的数组进行了扩容,但是我们的pos位置没有进行更新,发生了迭代器失效,我们的erase函数失效的原因是我们的vs会对他进行强制的判断,删除数据以后这个迭代器就失效了。

这个是我们的list底层实现的insert函数,我们的list没有扩容的问题,这里的insert是没有迭代器失效的问题的。

这个是我们的list的删除函数erase,这个函数和我们的vector一样,都是会发生迭代器失效的问题的,我们的erase函数,在把pos位置的数据删除以后,迭代器pos指向的结点就被销毁了,这时候pos就失效了,所以我们的这个函数还是要返回下一个数据的迭代器来及时的更新我们的迭代器,来避免迭代器的失效。

这样我们就可以向vector那样,删除数据以后,更新我们的迭代器;

(几乎所有的容器的erase都会失效,至于insert会不会失效,这个就要看情况);

const修饰迭代器:

我们看这个代码,我们在实现拷贝构造的时候,我们的参数传的是const修饰的参数类型,这时候我们进到函数里面的话,我们使用范围for就会报错,因为范围for的底层是我们的迭代器,我们的迭代器是普通的类型。

但是我们的链表被const修饰,我们使用迭代器对他进行遍历的话,我们就需要const类型的迭代器来。

我们看下面的图片:

我们的这个图片我们看我们的上面的两种被const修饰的指针,我们的const放在*前面的时候,我们的指针指向的数据不能被修改,但是我们的指针的指向可以修改。

当我们的const在*的右边的时候,这时候表示我们的指针指向的数据可以被修改,但是我们的指针的指向不能被修改。

我们的const迭代器其实就是和我们的上面的第一种是一样的,我们的迭代器指向的数据不能被修改,但是我们的迭代器的指向可以被修改;

所以,对于这种情况,我们就创建两种迭代器来进行应对:一种普通的迭代器,再来一种const修饰的迭代器;

我们把const迭代器封装成一个新的类,我们的const修饰的迭代器和普通的迭代器是两个不同的类;

这个是我们的const修饰的迭代器;

这个是我们的普通的迭代器;

这两个类的本质的却别其实就是解引用*的实现,const修饰的迭代器我们的返回值加上const,不能让他修改数据;

迭代器的合并:

我们实现我们的迭代器的封装,我们封装了两个类,分别是我们的普通的迭代器iterator的封装和const修饰的const_iterator的封装,但是其实这两个类的话,我们看了我们上面的const修饰的迭代器,其实主要的区别就是解引用函数的返回值是否是被const修饰的。

我们就可以再加一个模板参数,把我们的解引用函数的返回值换成我们的模板参数,然后我们调用我们的迭代器的时候,我们需要什么类型的迭代器,我们直接传参就可以了。

补充:

我们看这个图片,我们看我们对我们的vector进行初始化的状态。

v1.push_back({ 1,1 }); 等尾插操作涉及隐式类型转换。

AA 结构体定义了带有默认参数的构造函数 AA(int a1 = 1, int a2 = 1) 。当执行 v1.push_back({ 1,1 }); 时,花括号初始化列表 {1, 1} 没有直接对应的 AA 类型对象。此时,编译器会利用 AA 的这个构造函数,将 {1, 1} 隐式转换为 AA 类型临时对象,再调用 push_back 插入到 vector<AA> 容器 v1 中 。这符合隐式类型转换的特征,即编译器自动利用构造函数进行类型转换。

我们来看这个函数,我们上面使用vector容器,我们看vector里面使用了这个容器:

我们看这个,我们使用迭代器进行遍历然后使用箭头->解引用得到数据打印;

这个原理是什么呢?因为我们的vector的迭代器就是他的原生指针,我们的vector是一个顺序表,里面的每个元素的都是AA类型的对象,我们的迭代器指向某一个位置,这个位置的数据就是一个AA对象,那么这个迭代器就是指向这个位置的指针,那么这个指针就相当于是一个结构体struct指针,我们使用指针->得到结构体里面的数据a1和a2。

我们再看,当我们的容器换成list的时候,我们还是进行遍历打印数据,这时候我们直接->是不行的,我们的list的迭代器不是原生的指针,我们要自己封装实现;

我们看我们实现的;这个代码,我们返回我们的结点的数据的指针,我们的返回值是模板类型的,因为他可能是const修饰的指针,也可能不是const修饰的。

这是我们的迭代器的最后的模板;

我们继续回到上面看:

我们的->的返回值是结点里面的数据的指针,但是这个数据是AA类型的对象,我们还要再来一个箭头才是最终的_a1和_a2数据;  ,,但是这里是特殊的处理,省略了,方便可读。

这个是我们实现的完整的版本:

list的底层实现/list的底层实现/list的底层实现.h · 拾亿天歌/拾亿天歌 - 码云 - 开源中国

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

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

相关文章

遵循IEC62304YY/T0664:确保医疗器械软件生命周期合规性

一、EC 62304与YY/T 0664的核心定位与关系 IEC 62304&#xff08;IEC 62304&#xff09;是国际通用的医疗器械软件生命周期管理标准&#xff0c;适用于所有包含软件的医疗器械&#xff08;如嵌入式软件、独立软件、移动应用等&#xff09;&#xff0c;其核心目标是确保软件的安…

【next函数python】`next()`函数

在Python中&#xff0c;next()函数结合生成器表达式用于高效地查找序列中第一个符合条件的元素。以下是如何理解和编写类似代码的步骤&#xff1a; 1. 生成器表达式 生成器表达式&#xff08;如 (e for e in energy3 if e ! 0)&#xff09;是一种惰性计算的迭代结构。它不会一…

[创业之路-364]:穿透表象:企业投资的深层逻辑与误区规避

前言&#xff1a; 透过现象看本质 企业一生与人生相似 看企业如同看人 三岁看大&#xff0c;七岁看老 三十年河东&#xff0c;三十年河西 企业也有品行、文化、气质、性格、赚钱、生命周期与赚钱曲线 投资公司的目的是未来赚钱&#xff0c;赚未来赚钱。投资创业中的企业主要看…

【C++】Stack Queue 仿函数

&#x1f4dd;前言&#xff1a; 这篇文章我们来讲讲STL中的stack和queue。因为前面我们已经有了string、vector和list的学习基础&#xff0c;所以这篇文章主要关注一些stack和queue的细节问题&#xff0c;以及了解一下deque&#xff08;缝合怪&#xff09;和priority_queue &am…

[实战] 天线阵列波束成形原理详解与仿真实战(完整代码)

天线阵列波束成形原理详解与仿真实战 1. 引言 在无线通信、雷达和声学系统中&#xff0c;波束成形&#xff08;Beamforming&#xff09;是一种通过调整天线阵列中各个阵元的信号相位和幅度&#xff0c;将电磁波能量集中在特定方向的技术。其核心目标是通过空间滤波增强目标方…

深圳漫云科技户外公园实景儿童剧本杀小程序:开启亲子互动新纪元

在亲子娱乐需求日益增长的当下&#xff0c;深圳漫云科技推出的户外公园实景儿童剧本杀小程序&#xff0c;凭借其创新玩法与丰富功能&#xff0c;为亲子家庭带来全新体验。该小程序融合户外探险、角色扮演与逻辑推理&#xff0c;不仅满足孩子好奇心&#xff0c;更提升其思维能力…

HOW - 如何测试 React 代码

目录 一、使用 React 测试库&#xff1a;testing-library/react二、使用测试演练场&#xff1a;testing-playground.com三、使用 Cypress 或 Playwright 进行端到端测试四、使用 MSW 在测试中模拟网络请求 一、使用 React 测试库&#xff1a;testing-library/react testing-li…

COBOL语言的网络安全

COBOL语言与网络安全&#xff1a;传统语言的新挑战 引言 COBOL&#xff08;Common Business-Oriented Language&#xff09;是一种早期编程语言&#xff0c;最初于1959年被开发出来&#xff0c;主要用于商业、金融和行政系统的处理。尽管年代久远&#xff0c;COBOL在大型机系…

通过世界排名第一的免费开源ERP,构建富有弹性的智能供应链

概述 现行供应链模式的结构性弱点凸显了对整个行业进行重塑的必要性。正确策略和支持可以帮助您重塑供应链&#xff0c;降低成本&#xff0c;实现业务转型。开源智造&#xff08;OSCG&#xff09;所推出的Odoo免费开源ERP解决方案&#xff0c;将供应链转化为具有快速响应能力的…

Android 开发中compileSdkVersion 和 targetSdkVersion

在 Android 开发中&#xff0c;compileSdkVersion 和 targetSdkVersion 是 build.gradle 文件中的两个关键配置&#xff0c;它们分别控制应用的编译行为和运行时兼容性。以下是它们的详细区别和用途&#xff1a; 1. compileSdkVersion&#xff08;编译版本&#xff09; 作用&a…

Qt QComboBox 下拉复选多选

Qt 中&#xff0c;QComboBox 默认只支持单选&#xff0c;但实际使用过程中&#xff0c;我们经常会碰到需要多选的情况&#xff0c;但是通过一些直接或者曲折的方法还是可以实现的。 1、通过 QListWidget 间接实现 这种方式是网上搜索最多的一种方式&#xff0c;也是相对来说比…

Selenium自动化:玩转浏览器,搞定动态页面爬取

嘿&#xff0c;各位爬虫爱好者和自动化达人们&#xff01;是不是经常遇到这种情况&#xff1a;信心满满地写好爬虫&#xff0c;requests一把梭&#xff0c;结果抓下来的HTML里&#xff0c;想要的数据空空如也&#xff1f;定睛一看&#xff0c;原来数据是靠JavaScript动态加载出…

天梯赛 L2-023 图着色问题

使用vector<vector<int>> g(N)去存储边&#xff0c;然后每次判断每个节点的邻节点是不是相同的颜色&#xff0c;需要注意的是不同的颜色一定需要为K种&#xff0c;不能多也不能少。 #include<bits/stdc.h> using namespace std; int main(){int n,m,k;cin&g…

在ubuntu24上装ubuntu22

实验室上有一台只装了ubuntu24的电脑&#xff0c;但是项目要求在22上进行 搞两个ubuntu系统&#xff01; 步骤一&#xff1a;制作22的启动盘 步骤二&#xff1a;进入bios安装界面 步骤三&#xff1a;选择try or install ubuntu 步骤四&#xff1a;选择try ubuntu 步骤五&…

【PVR Review】《Review of Deep Learning Methods for Palm Vein Recognition》

[1]谭振林,刘子良,黄蔼权,等.掌静脉识别的深度学习方法综述[J].计算机工程与应用,2024,60(06):55-67. 文章目录 1、Background and Motivation2、数据采集3、掌脉图像预处理3.1、ROI提取算法3.2、图像滤波与增强 4、掌脉识别算法4.1、基于深度学习的方法4.2、其他方法 5、融合识…

【CSP】202403-1词频统计

文章目录 算法思路1. 数据结构选择2. 输入处理3. 统计出现的文章数4. 输出结果 代码示例代码优化 样例输入 4 3 5 1 2 3 2 1 1 1 3 2 2 2 2 3 2样例输出 2 3 3 6 2 2算法思路 1. 数据结构选择 vector<int>&#xff1a;用于存储每篇文章的单词列表&#xff08;可能包含…

Docker基础1

本篇文章我将从系统的知识体系讲解docker的由来和在linux中的安装下载 随后的文章会介绍下载镜像、启动新容器、登录新容器 如需转载&#xff0c;标记出处 docker的出现就是为了节省资本和服务器资源 当企业需要一个新的应用程序时&#xff0c;需要为它买台全新的服务器。这样…

Linux系统学习Day04 阻塞特性,文件状态及文件夹查询

知识点4【文件的阻塞特性】 文件描述符 默认为 阻塞 的 比如&#xff1a;我们读取文件数据的时候&#xff0c;如果文件缓冲区没有数据&#xff0c;就需要等待数据的到来&#xff0c;这就是阻塞 当然写入的时候&#xff0c;如果发现缓冲区是满的&#xff0c;也需要等待刷新缓…

vue 3 从零开始到掌握

vue3从零开始一篇文章带你学习 升级vue CLI 使用命令 ## 查看vue/cli版本&#xff0c;确保vue/cli版本在4.5.0以上 vue --version ## 安装或者升级你的vue/cli npm install -g vue/cli ## 创建 vue create vue_test ## 启动 cd vue_test npm run servenvm管理node版本&#…

Mysql专题篇章

一、事务的四大特性&#xff1f; 1、原子性&#xff1a;是指事务包含的所有操作要么全部成功&#xff0c;要么全部失败回滚。 2、一致性&#xff1a;是指一个事务执行之前和执行之后都必须处于一致性状态。比如a与b账户共有100块&#xff0c;两人之间转账之后无论成功还是失败…