《STL--list的使用及其底层实现》

引言:

上次我们学习了容器vector的使用及其底层实现,今天我们再来学习一个容器list
这里的list可以参考我们之前实现的单链表,但是这里的list双向循环带头链表,下面我们就开始list的学习了。

一:list的介绍

list的介绍文档:

二:list的使用

1. 约定:

关于list的接口众多,下面我们只介绍一些比较常用的接口,其他接口同学们可以自行去list的介绍文档中学习。

2. list的构造:

  1. list (size_type n, const value_type& val =value_type()):构造的list中包含n个值为val的元素。
  2. list():构造空的list
  3. list (const list& x):拷贝构造函数。
  4. list (InputIterator first, InputIterator last):[first, last)区间中的元素构造
    list
代码演示:

在这里插入图片描述

3.list iterator的使用

注:这里大家先将list的迭代器理解为指向节点的一个指针。

  1. begin:返回第一个元素的迭代器。
  2. end:返回最后一个元素下一个位置的迭代器。
  3. rbegin:返回第一个元素的reverse_iterator,即end位置。
  4. rend:返回最后一个元素下一个位置的reverse_iterator,即begin位置。
代码演示:

在这里插入图片描述
注:

  1. beginend为正向迭代器,对迭代器执行++操作,迭代器向后移动
  2. rbegin(end)rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

4.list capacity的使用

  1. empty:检测list是否为空,为空返回true,反之则返回false
  2. size:计算list中有效数据的个数。
代码演示:

在这里插入图片描述

5. list element access

  1. front:返回list的第一个节点中值的引用。
  2. back:返回list的最后一个节点中值的引用。
代码演示:

在这里插入图片描述

6. list modifiers

  1. push_front:list首元素前插入值为val的元素。
  2. pop_front:删除list中第一个元素。
  3. push_back:list尾部插入值为val的元素。
  4. pop_back:删除list中最后一个元素。
  5. insert:list position 位置中插入值为val的元素。
  6. erase:删除list position位置的元素。
  7. swap:交换两个list中的元素。
  8. clear:清空list中的有效元素。
代码演示:
(1)push_back(front) pop_back(front)

在这里插入图片描述

(2)eraseinsert

在这里插入图片描述
在这里插入图片描述

swapclear

在这里插入图片描述
在这里插入图片描述

7. list迭代器失效问题

前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

在这里插入图片描述

这里想要解决迭代器失效的话,处理方式和之前是一样的,需要对其重新进行赋值:

在这里插入图片描述

三:list的模拟实现

1. 思考:

这里在模拟实现list时就和vector的实现有所区别了,之前实现的vector的本质上一个数组,其迭代器和原生指针没什么区别,对其迭代器解引用就可以拿到对应的数据,但是这里的list里面存储的是一个个节点,因此这里的迭代器并不是单纯的原生指针,你对节点指针解引用的话拿到的是一个节点,并不能直接拿到节点里的数据,但是这不是我们期望的,按照我们的逻辑是解引用节点指针是要拿到这个节点指针对应节点里面的数据,因此这里在模拟实现的时候就比之前要复杂一点,牵扯到迭代器的构造以及有关迭代器的一些重载。

2.基本框架:

(1)节点结构:

在这里插入图片描述

(2)迭代器结构:

在这里插入图片描述

(3)链表结构:

在这里插入图片描述

3. 迭代器结构完善

(1)* 重载:

在这里插入图片描述

(2) 前置++和后置++重载:

在这里插入图片描述

(3) 前置- - 和后置 - - 重载:

在这里插入图片描述

(4) 比较运算符重载:

在这里插入图片描述

4. 构造函数

在这里插入图片描述
注:这里在构造的过程中由于会对e进行解引用,因此这里要用引用。

5. beginend

在这里插入图片描述

6. insert 函数

在这里插入图片描述
注:由于这里除了数据的申请,其他的逻辑和之前实现的双向链表没啥区别,就不细讲了。

7. push_back 函数

在这里插入图片描述
注:这里就直接复用insert即可。

8. push_front 函数

在这里插入图片描述

9. erase 函数

在这里插入图片描述
注:

  1. 这里需要注意头结点我们是不能动的。(大哥动不得
  2. 为解决erase引起的迭代器失效问题,这里我们的erase给了返回值。

10. pop_back 函数

在这里插入图片描述
注:这里就是直接复用erase即可。

11. pop_front 函数

在这里插入图片描述

12. clear 函数

在这里插入图片描述

13. 析构函数

在这里插入图片描述

14. size 函数

注:为了避免重复遍历链表来计算个数,因此这里我们就来维护一个成员变量_size,因此之前的插入和删除都需要维护_size
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

15. swap 函数

在这里插入图片描述

四: 拷贝构造函数引起的问题及解决方案

1. 问题的引发

我们这里在实现拷贝构造函数的时候出现了以下问题:
在这里插入图片描述
那么为什么会出现这个问题呢?

2. 思考:

因为拷贝构造函数这里给的参数是const类类型,但是这里在构造的过程中用到了范围for,我们知道,范围for本质上就是迭代器的替换,并且因为需要进行解引用,所以这里的范围for我们用的是引用,但是由于传入参数是const类型,这里需要const类型的迭代器来支持,所以这里才会出现问题,因此我们就需要实现const类型的迭代器。

3. 解决方案:

这里由于const迭代器和普通类型的迭代器就一点不同,如果再封装一个类的话就太冗余了,因此这里就可以从模版下手:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个时候就解决了上面出现的问题,而且这样使得我们在使用不同的迭代器时编译器能够自动推导类型。

4. 赋值运算符重载:

在这里插入图片描述

五:补充内容— -> 重载

1. 引入:

首先我们来看vector存储自定义类型时的访问:

在这里插入图片描述
在这里插入图片描述
下面再来看用list来存储自定义类型时的访问:

在这里插入图片描述

可以看到用list来存储自定义类型的时候就不能用->来访问,这是为什么呢?
还是回到前面提到的迭代器的区别,vector的迭代器就可以理解为原生指针,用->就可以拿到其里面的数据,而list这里的迭代器->的话拿到的是节点,而不是数据,因此,这里这样写就有问题,那么我们看一下标准库里面的list的->
在这里插入图片描述

可以看到标准库里面的list就可以通过->来访问数据,这是因为标准库里的list->进行了特殊处理,因此我们这里也需要对->进行重载才可以。

2. -> 重载:

在这里插入图片描述
:这里->的重载看着就有点奇怪了,注意这里返回的是指向数据的指针(数据的地址)
在这里插入图片描述
在这里插入图片描述
注意这里的两种写法都可以,第一种方式只是编译器对其进行了特殊处理,其实第二种写法更符合我们理解的逻辑。

完结!!!

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

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

相关文章

docker中使用openresty

1.为什么要使用openresty 我这边是因为要使用1Panel,第一个最大的原因,就是图方便,比较可以一键安装。但以前一直都是直接安装nginx。所以需要一个过度。 2.如何查看openResty使用了nginx哪个版本 /usr/local/openresty/nginx/sbin/nginx …

vscode包含工程文件路径

在 VSCode 中配置 includePath 以自动识别并包含上层目录及其所有子文件夹,需结合通配符和相对/绝对路径实现。以下是具体操作步骤及原理说明: 1. 使用通配符 ** 递归包含所有子目录 在 c_cpp_properties.json 的 includePath 中,${workspac…

【排序算法】典型排序算法 Java实现

以下是典型的排序算法分类及对应的 Java 实现,包含时间复杂度、稳定性说明和核心代码示例: 一、比较类排序(通过元素比较) 1. 交换排序 ① 冒泡排序 时间复杂度:O(n)(优化后最优O(n)) 稳定性&…

多模态大语言模型arxiv论文略读(八十七)

MG-LLaVA: Towards Multi-Granularity Visual Instruction Tuning ➡️ 论文标题:MG-LLaVA: Towards Multi-Granularity Visual Instruction Tuning ➡️ 论文作者:Xiangyu Zhao, Xiangtai Li, Haodong Duan, Haian Huang, Yining Li, Kai Chen, Hua Ya…

塔能节能平板灯:点亮苏州某零售工厂节能之路

在苏州某零售工厂的运营成本中,照明能耗占据着一定比例。为降低成本、提升能源利用效率,该工厂与塔能科技携手,引入塔能节能平板灯,开启了精准节能之旅,并取得了令人瞩目的成效。 一、工厂照明能耗困境 苏州该零售工厂…

数据库事务的四大特性(ACID)

一、前言 在现代数据库系统中,事务(Transaction)是确保数据一致性和完整性的重要机制。事务的四大特性——原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)…

8 种快速易用的Python Matplotlib数据可视化方法

你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python 的 Matplotlib 库是你数据可视化的最佳伙伴!它简单易用、功能强大,能将枯燥的数字变成引人入胜的图表。无论是学生、数据分析师还是程序员&…

springboot 控制层调用业务逻辑层,注入报错,无法自动装配 解决办法

报错: 解决:愿意是业务逻辑层,即service层的具体实现类没有加注解Service导致的,加上解决了!!

如何提高独立服务器的安全性?

独立服务器相对于其它服务器来说,整体的硬件设备都是独立的同时还有着强大的服务器性能,其中CPU设备能够决定着服务器的运算能力,所以独立服务器的安全性受到企业格外的重视,严重的话会给企业造成巨大的资金损失。 那么&#xff0…

关于 Web 风险点原理与利用:6. 逻辑风险点

一、分类: 1.1 越权访问 **越权访问(Authorization Bypass)**是指:攻击者绕过了权限控制机制,访问或操作了非其权限范围内的资源或功能。 换句话说,系统该拦你没拦,你就越权成功了。 1.1.1 …

分布式缓存:ZSET → MGET 跨槽(cross‐slot)/ 并发 GET解决思路

文章目录 缓存全景图Pre问题描述解决思路一、管道(Pipelining)替代多线程二、使用 Hash Tag 保证数据同槽三、用 Hash 结构一次性批量取值四、把数据直接存进 ZSET(或用 RedisJSON) 小结 缓存全景图 Pre 分布式缓存:缓…

开发AR导航助手:ARKit+Unity+Mapbox全流程实战教程

引言 在增强现实技术飞速发展的今天,AR导航应用正逐步改变人们的出行方式。本文将手把手教你使用UnityARKitMapbox开发跨平台AR导航助手,实现从虚拟路径叠加到空间感知的完整技术闭环。通过本教程,你将掌握: AR空间映射与场景理…

助力 FPGA 国产化,ALINX 携多款方案亮相深圳、广州“紫光同创 FPGA 技术研讨会”

5 月中旬,一年一度的紫光同创技术研讨会系列活动正式拉开帷幕,相继在深圳、广州带来 FPGA 技术交流盛宴。 ALINX 作为紫光同创官方合作伙伴,长期助力推动 FPGA 国产化应用发展,此次携多款基于 Kosmo-2 系列产品开发的方案 demo 亮…

LeetCode 1040.移动石子直到连续II

在 X 轴上有一些不同位置的石子。给定一个整数数组 stones 表示石子的位置。 如果一个石子在最小或最大的位置,称其为 端点石子。每个回合,你可以将一颗 端点石子 拿起并移动到一个未占用的位置,使得该石子不再是一颗 端点石子。 值得注意的…

梯度优化提示词:精准引导AI分类

基于梯度优化的提示词工程方法,通过迭代调整提示词的嵌入向量,使其能够更有效地引导模型做出正确分类。 数据形式 训练数据 train_data 是一个列表,每个元素是一个字典,包含两个键: text: 需要分类的文本描述label: 对应的标签(“冲动"或"理性”)示例数据: …

JavaWeb:SpringBoot配置优先级详解

3种配置 打包插件 命令行 优先级 SpringBoot的配置优先级决定了不同配置源之间的覆盖关系,遵循高优先级配置覆盖低优先级的原则。以下是详细的优先级排序及配置方法说明: 一、配置优先级从高到低排序 1.命令行参数 优先级最高,通过keyvalu…

使用CentOS部署本地DeekSeek

一、查看服务器的操作系统版本 cat /etc/centos-release二、下载并安装ollama 1、ollama下载地址: Releases ollama/ollama GitHubGet up and running with Llama 3.3, DeepSeek-R1, Phi-4, Gemma 3, Mistral Small 3.1 and other large language models. - Re…

Matplotlib 后端与事件循环

前言:很多时候,matplot跑出来的是这种静态非交互的,如果想要可以交互,就得设定一个后端,例如 matplotlib.use(TkAgg)Matplotlib 后端 (Backend) Matplotlib 的设计理念是能够以多种方式输出图形,无论是显…

【JAVA】中文我该怎么排序?

📘 Java 中文排序教学文档(基于 Collator) 🧠 目录 概述Java 中字符串排序的默认行为为什么需要 Collator使用 Collator 进行中文排序升序 vs 降序排序自定义对象字段排序多字段排序示例总结对比表附录:完整代码示例 …

k8s-NetworkPolicy

在 Kubernetes 中,NetworkPolicy 是一种资源对象,用于定义 Pod 之间的网络通信策略。它允许你控制哪些 Pod 可以相互通信,以及如何通信。通过使用 NetworkPolicy,可以实现更细粒度的网络访问控制,增强集群的安全性。 1…