list底层原理
一.结构体的构建
这个用结构体更好,因为我们需要不断的访问节点,类中的成员函数一般都是私有的,需要还用友元函数什么的。
这个是我们来实现的类,我们实现的是双向带头循环链表,这个是实用性最高的一个链表的形式。
这个_head就是一个头的作用,没有实际意义。
二.构造函数
这个就是我们的构造函数了,这个就是给头申请一块空间,让next和prev都指向头节点,这样就不会出现空指针的问题了,更加的方便。
三.push_back
这个是我们的插入函数,大家可以结合下面的图理解着看一下。
大家可以结合着上面的代码自己画一下图就很好理解了,这个就是创建一个新节点,然后先找到原来链表的最后一个节点也就是_head->prev,然后再让链表的最后一个元素指向新的节点,再让新的节点的next指向_head,再让新的节点的prev指向指向原链表的最后一个节点,最后让_head的prev指向新节点即可。
四.迭代器
下面来实现一下迭代器。
我们会遇到一些问题,我们难道也要像实现vector的迭代器一样,实现一个指针吗?
typedef list_node<T>* iterator;//这样实现会面临很多问题,我们的解引用是一个结构体而不是一个值,况且空间不连续,我们的++操作也没法完成,那我们该怎么办呢?
我们可以封装一个结构体来完成。
这就是我们迭代器的所需的一个结构体,就是通过node来接收我们的list_node<T>的结构体,通过构造初始化,就是传入我们需要的节点,接下来我们来完成迭代器的一些基本操作吧。
4.1 operator*()
通过赋值运算符的重载直接返回这个节点的值就可以了。
4.2 operator++()
这个就是我们的++操作,直接让我们的node=node->_next即可完成,也是很简单的。
4.3 operator!=()
这个就是两个list_iterator<T>对象进行比较的,通过比较它们的node是否相等即可。
4.4 operator==()
这个就是把上面的代码的!=改成等于了。
4.5 begin()和end()
这就是我们完成的begin和end函数,返回了iterator对象。
接下来我们来测试一下。
我们发现都是符合我们的预期的。
五.const的迭代器
我们都知道迭代器一般都有两种一种是普通版本的,一种则是const版本的。
const版本的实现起来也是很简单的。
这就是我们的const版本的迭代器,也是很简单的,只需要改一下返回值什么的就行了。
这是它的begin和end方法。
为什么报错了呢?
因为l1不是const类型的,它会优先匹配自己的迭代器,而不是const类型的迭代器,两个不同的类型都是优先匹配到自己的类型的begin和end方法。
这个就是it是const_iterator类型的,但是l1.end()是iterator类型的,类型不匹配。
我们发现出现了问题,无法使用*,因为我们的A类中没有重载。
如图所示就得到了解决,但是又发现了几个常犯的错误,那为什么我这里的l1调用不到const类型的begin和end函数呢?实际上,非 const 对象 l1 是可以调用 const 版本的 begin 和 end 函数的。不过,当非 const 对象调用成员函数时,编译器会优先选择非 const 版本的函数。
为什么我们的l2调用不到其他的函数呢?当你在qrh::list<A<int>>前面加上const后,该对象就成为了常量对象。对于常量对象,只能调用其const成员函数。
最后一条语句也可以验证我们上面所说的类型。
我们来看一下结果。
和我们想的一样,就是list_iterator类型的。
还有一种方法就是->的运算符,也是可以访问到自定义类型中的变量的。
5.1 operator->()
就是这种形式,可以大家刚开始看的时候有些迷茫,为什么返回node->_data的地址呢?
你可以理解为因为要返回一个指针,指针才具有->操作符。
我们来看一下,返回了node->_data的地址,应该是两个箭头的,第一个箭头先找到了_node->_data再来一个箭头才能访问得到其中的变量啊,因为编译器做优化了,两个箭头的可读性太低了,所以优化为一个箭头了,了解知道就行。
六.合并两个迭代器
上面是我们正常思路是要写两个的,但是我们可以观察一下它们的共同之处。
你看它们的这些方法只是返回值的类型不同罢了,一个是T,一个是const T,其他方法都是相同的,只有这两个方法需要区别一下,其实我们就可以使用函数模板,把它弄成一个就行了,接下来看我操作。
我们又加了两个模板参数,我们通过传参的不同可以区别这两个迭代器的类型。
看见没,我们通过控制后面两个参数的不同就可以区别出迭代器了,这是一个非常厉害的方法。
这样就可以把两个迭代器只写一个结构体就可以了。
我们接下来来完成剩下的一些常用的方法吧。
七.insert()
这个就是通过迭代器插入。
我们的思路是我们首先先找到我们所要插入的位置,然后再找到它的前一个位置,然后让前一个位置的_next指向newnode,newnode的_prev指向newnode,再让newnode的_next指向cur,再让cur的_prev指向newnode即可。
size表示链表的长度。
通过这个我们也可以简化一下我们的push_back了。
八.erase
这个就是通过迭代器位置删除该位置。
我们还是先找到我们需要删除的位置,然后再找到它的前一个位置和后一个位置,然后让前一个位置的_next指向下一个位置,让下一个位置的_prev指向前一个位置,再把当前位置的空间释放了,再把size--即可,最后的返回值的作用就是防止迭代器失效的,一会儿下面有样例。
九.push_front 和pop_back 和 pop_feont
我们等会儿再写--的操作,这些都很简单,看一下就行了。
我们来测试一下我们写的代码。
发现是符合我们预期的。
十.operator--
这个就很简单了。
十一.后置--和后置++
这个我们在之前的运算符重载都讲过,这里就不在详细展开讲了,不懂的可以看之前的博客。
十二.clear
这就是我们的clear函数了,这里也体现了我们上面说的迭代器失效的问题了,如果我们不给返回值的话,此时it这个迭代器就会失效了,由于指向了一块被释放的空间,导致迭代器失效了。
十三.拷贝构造
不写的话就默认是浅拷贝了,可能会出现同一块空间被释放两次的场景。
举个浅拷贝的例子吧。
我们先跑一下看看。
我们发现程序崩溃了,就是发生了浅拷贝,两个对象指向了同一块空间,当其中一个对象被clear了,导致另一个对象指向了一块野指针的空间,导致打印不出来结果,此时程序就会崩溃了。
我们在写了深拷贝之后就不会出现这样的问题了。
没有问题。
十四.operator=()
这个是最新版的函数,想要详细的讲解可以看vector底层的那篇博客,里面有详细的讲解。
如果我们没有重载这个的话,默认还是浅拷贝,我们再来演示一下。
我们来看一下。
虽然打印出来结果了,但是程序还是崩溃了。原因就是浅拷贝使它俩指向了同一块空间,所以同一块空间被释放了两次,导致了程序的崩溃。
所以我们就必须写。
十五.结束语
感谢大家的查看,希望可以帮助到大家,做的不是太好还请见谅,其中有什么不懂的可以留言询问,我都会一一回答。 感谢大家的一键三连。
相关文章:
list底层原理
一.结构体的构建 这个用结构体更好,因为我们需要不断的访问节点,类中的成员函数一般都是私有的,需要还用友元函数什么的。 这个是我们来实现的类,我们实现的是双向带头循环链表,这个是实用性最高的一个链表的形式。 这…...
python+selenium+pytest自动化测试chrome driver版本下载
chrome浏览器chromedriver版本下载地址 https://googlechromelabs.github.io/chrome-for-testing/#stable...
发布一个npm包,更新包,删除包
发布一个npm包,更新包,删除包 如何将自己的项目 发布为一个 npm 包,并掌握 更新 和 删除 的操作流程。 🚀 一、发布一个 npm 包的完整流程 ✅ 1. 注册并登录 npm 账号 如果还没有账号,先注册: 官网注册&…...
代码随想录训练营38天 || 322. 零钱兑换 279. 完全平方数 139. 单词拆分
322. 零钱兑换 思路: 动规5部曲: 1.确定dp数组以及下标的含义: dp数组表示能凑出零钱的最少硬币数,下标表示要兑换的零钱 2.确定递推公式: j为背包容量,i为物品的下标 dp[ j ] min(dp[ j -coins[ i…...
(最新)华为 2026 届校招实习-硬件技术工程师-硬件通用/单板开发—机试题—(共14套)(每套四十题)
(最新)华为 2026 届校招实习-硬件技术工程师-硬件通用/单板开发—机试题—(共14套)(每套四十题) 本套题目为硬件通用题目,适合多个岗位方向,如下 **岗位——硬件技术工程师 岗位意向…...
IOT项目——DIY Weather Station With ESP32
开源项目:ESP32 气象站 作者:GiovanniAggiustatutto 原文链接: ESP32 气象站 温度设备塔风向标风速计雨量计框架电子元件和压力传感器家庭助理配置及应用 气象站测量温度、湿度、气压、风速和风向以及降雨量。所有数据均由 ESP32收集…...
表格识别版面还原分析-GO语言集成-表格文字识别接口
数据驱动的时代,高效处理和分析各类文档中的信息变得尤为重要。无论是金融服务中的报表分析,制造与物流行业的库存管理,还是医疗卫生领域的病历记录,快速准确地将纸质或电子表格中的数据转换为可编辑、保存的电子数据成为提升工作…...
文件上传漏洞3
1. 例题:文件上传限制 1)上传漏洞靶场介绍 项目名称: upload-labs开发语言: 使用PHP语言编写功能定位: 专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场关卡数量: 目前共21关,每关包含不同上传方式注意事项: 每关没有固定通关方法,不要自限…...
一洽智能硬件行业解决方案探索与实践
一、智能硬件行业发展现状剖析 在数字化浪潮推动下,智能硬件行业呈现蓬勃发展态势。软硬件一体化的深度融合,构建起智能化服务的核心架构,而移动应用作为连接用户与设备的重要桥梁,其作用愈发关键。深入研究该行业,可…...
什么是snmp协议?在优雅草星云智控AI物联网监控系统中如何添加设备进行监控【星云智控手册01】-优雅草卓伊凡
什么是snmp协议?在优雅草星云智控AI物联网监控系统中如何添加设备进行监控【星云智控手册01】-优雅草卓伊凡 优雅草星云智控物联网设备 本产品即将在5月15日在优雅草科技的承办下召开产品发布会,本产品需要报名参加可以通过活动行搜索星云智控进行报名…...
神经网络权重优化秘籍:梯度下降法全解析(五)
引言 在神经网络的训练过程中,权重更新是提升模型性能的关键环节,而梯度下降法及其优化算法则是实现这一关键环节的核心工具。理解并掌握这些方法,对于打造高效的神经网络模型至关重要。本文将深入剖析梯度下降法在神经网络权重更新中的应用…...
输入框仅支持英文、特殊符号、全角自动转半角 vue3
需求:封装一个输入框组件 1.只能输入英文。 2.输入的小写英文自动转大写。 3.输入的全角特殊符号自动转半角特殊字符 效果图 代码 <script setup> import { defineEmits, defineModel, defineProps } from "vue"; import { debounce } from "…...
Python简介与入门
目录 Python初始 Python的优势 Python 的特性 Linux下安装Python windows 系统安装python Python的语法基础 标识符 注释 语句与缩进 Python 常用的数据类型 数字 字符串 列表 列表的定义 列表的取值 重复列表 元组 元组的操作 字典 字典的创建 字典的取值操作 字典的添加、…...
C++学习笔记(三十六)——STL之排序算法
一、STL 算法 C的STL(Standard Template Library) 提供了一组高效、通用的算法,这些算法适用于各种容器(如 vector、list、set、map)。 这些算法主要位于 <algorithm> 和 <numeric> 头文件中。 通用性&a…...
G1 人形机器人软件系统架构与 Python SDK
如果说人形机器人的硬件是它的“身体”,那么软件系统就是它的“大脑”和“神经系统”,负责接收信息、进行决策并控制身体行动。理解 G1 机器人的软件架构,特别是如何通过编程接口与其交互,是进行机器人开发的核心。本节将剖析 G1 …...
Redis在SpringBoot中的使用
在SpringBoot项目中使用redis存储数据作为字典 本项目使用jdk1.8 一、添加依赖 <!-- spring boot redis缓存引入 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>…...
SuperMap GIS基础产品FAQ集锦(20250421)
一、SuperMap iDesktopX 问题1:iDesktopX怎么根据对数据集中的每条记录进行批量布局出图? 11.3.0 【解决办法】打开地图系列设置功能,勾选启用并设置索引地图,索引图层和索引字段等参数,打印地图册,设置输出路径&am…...
Linux学习笔记2
1.man man指令相当于一个在线手册 使用q可以退出指令运行 例如,使用 man ls 指令可以得到以下运行结果: 在查找的时候还可以使用数字,使用 man man 指令,对应每个数字所表示的内容: 在Linux下,一切皆是文件…...
电脑安装adb并且连接华为手机mate60pro后查看设备
1.下载adb工具 下载地址: https://developer.android.google.cn/tools/releases/platform-tools?hlzh-cn#downloads 根据需要下载自己系统需要的安装包 下载后解压 2.配置adb工具环境变量 添加ADB_HOME D:\softwares\platform-tools-latest-windows\platform-…...
EAL4+与等保2.0:解读中国网络安全双标准
EAL4与等保2.0:解读中国网络安全双标准 在当今数字化时代,网络安全已成为各个行业不可忽视的重要议题。特别是在金融、政府、医疗等领域,保护信息的安全性和隐私性显得尤为关键。在中国,EAL4和等级保护2.0(简称“等保…...
树莓派学习专题<8>:使用V4L2驱动获取摄像头数据--获取摄像头支持的分辨率
树莓派学习专题<8>:使用V4L2驱动获取摄像头数据--获取摄像头支持的分辨率 1. 获取摄像头支持的分辨率2. 代码分析3. 树莓派实测 1. 获取摄像头支持的分辨率 使用如下代码获取摄像头支持的输出分辨率。 struct v4l2_frmsizeenum stFrameSize …...
CSS预处理器对比:Sass、Less与Stylus如何选择
引言 CSS预处理器已成为现代前端开发的标准工具,它们通过添加编程特性来增强纯CSS的功能,使样式表更加模块化、可维护且高效。在众多预处理器中,Sass、Less和Stylus是三个最流行的选择,它们各自拥有独特的语法和功能特点。本文将深…...
Vue3集成sass
安装依赖 pnpm add -D sass-embedded配置全局变量 新建文件 src/styles/variables.scss配置Vite 修改 vite.config.ts variables.scss $base-color: bluevite.config.ts // https://vite.dev/config/ export default defineConfig({plugins: [vue(),],resolve: {alias: {:…...
超越Dify工作流:如何通过修改QwenAgent的Function Call及ReAct方法实现对日期时间的高效意图识别
在构建复杂的AI应用时,意图识别是一个至关重要的环节。传统上,许多开发者会使用Dify工作流来完成这一任务,但在处理复杂意图时,这种方法往往需要大模型进行多级反复识别,从而带来较高的时间成本。 本文将介绍如何通过修改QwenAgent框架中的FnCallAgent和ReActChat类,实现…...
Lua 第8部分 补充知识
8.1 局部变量和代码块 Lua 语言中的变量在默认情况下是全局变量 ,所有的局部变量在使用前必须声明 。 与全局变量不同,局部变量的生效范围仅限于声明它的代码块。一个代码块( block )是一个控制结构的主体,或是一个函…...
Lua 第7部分 输入输出
由于 Lua 语言强调可移植性和嵌入性 , 所以 Lua 语言本身并没有提供太多与外部交互的机制 。 在真实的 Lua 程序中,从图形、数据库到网络的访问等大多数 I/O 操作,要么由宿主程序实现,要么通过不包括在发行版中的外部库实现。 单就…...
Java 中 == 和 equals() 的区别
1. 运算符 是 Java 中的比较运算符,用于比较两个变量的值是否相等,但具体行为取决于变量的类型: 类型 比较的内容基本类型直接比较值是否相等(如 int a 5; int b 5; a b 返回 true)引用类型比较内存地址&#x…...
Redis新节点加入集群会发生什么(面试题)
新加入主节点:会发生槽位数据重新分配迁移, 新加入从节点,会发生主从同步,全量同步和增量同步 当一个新节点加入 Redis 集群时,会触发一系列操作以确保集群的稳定性和数据的一致性。以下是新节点加入 Redis 集群时的详…...
dmncdm达梦新云缓存数据库主从集群安装部署详细步骤说明
dmncdm达梦新云缓存数据库主从集群安装部署详细步骤说明 1 环境介绍2 安装部署dmncdm2.1 196部署cdm环境2.2 197部署cdm环境2.3 190部署cdm环境 3 主备集群/主从集群配置4 部署主备集群/主从集群5 部署日志6 更多达梦数据库全方位指南:安装 优化 与实战教程 1 环境介绍 cpu x8…...
docker容器,mysql的日志文件怎么清理
访问问题 你的问题是因为在当前路径 /home/ictrek/data/ragflow-mysql 下没有名为 data 的子目录。以下是详细分析和解决方法: 错误原因 路径不存在 当前目录 /home/ictrek/data/ragflow-mysql 下没有名为 data 的子目录,执行 cd data/ 时会报错 No suc…...
kafka auto.offset.reset详解
在 Kafka 中,auto.offset.reset latest 的含义及行为如下: 1. 核心定义 当消费者组首次启动或无法找到有效的 offset(例如 offset 过期、被删除或从未提交)时,消费者会从分区的最新位置…...
设备制造行业如何避免项目管理混乱?
项目常因进度延误、成本超支或部门协作不畅而陷入混乱? 这不仅拖累项目交付,还可能损害客户信任和企业利润。设备制造行业的项目管理复杂多变,从需求获取到生产交付再到售后运维,每一个环节都可能成为效率的瓶颈。 如何破解这一…...
kubernetes》》k8s》》删除命名空间
使用 kubectl delete ns 命名空间 --force --grace-period0 如果还删除不掉 需要 kubectl get namespace 命名空间 -o json > x.json vim x.json kubectl replace --raw “/api/v1/namespaces/命名空间/finalize” -f ./x.json...
【深度学习新浪潮】新视角生成的研究进展调研报告(2025年4月)
新视角生成(Novel View Synthesis)是计算机视觉与图形学领域的核心技术,旨在从单张或稀疏图像中生成任意视角的高保真图像,突破传统多视角数据的限制,实现对三维场景的自由探索。作为计算机视觉与图形学的交叉领域,近新视角生成年来在算法创新、应用落地和工具生态上均取…...
55、Spring Boot 详细讲义(十一 项目实战)springboot应用的登录功能和权限认证
项目文档:springboot应用的登录功能和权限认证 一、项目概述 1. 项目简介 本项目是在一个基于Spring Boot的Web应用中实现登录功能和权限认证。要求实现登录功能,用户登录成功以后,会给前台返回当前登录用户可以访问的权限菜单,比如超级管理员可以访问所有权限,产品管理…...
react 父子组件通信 子 直接到父, 父 forwardref子
React核心概念:单向数据流(Unidirectional Data Flow) React 中数据的流动像瀑布一样,只能从上层组件(父组件)流向下层组件(子组件)。 子组件无法直接反向修改父组件的数据&#x…...
基于TCP的协议
目录 TCP 基于TCP的应用层协议: TCP的工作方式 TCP TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层协议。它为应用层提供了一个可靠的端到端的数据传输服务。再TCP/IP模型中,TCP位于传输层,负责再…...
性能比拼: Go vs Java
本内容是对知名性能评测博主 Anton Putra Go (Golang) vs Java: Performance Benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本视频中,我们将比较 Go 和 Java。 我们将基于 Golang 的 Fiber 框架和 Java 的 Spring Boot 创建几个简单的应用…...
【Spring】单例作用域下多次访问同一个接口
在Spring框架中,Controller和Service的Bean默认都是单例(Singleton)的。在多个请求同时访问Controller时,Service的Bean调用情况如下: 1. 核心机制 单例Bean:Spring容器为每个Bean定义(如Serv…...
数据库介绍
1、什么是数据库 数据库是一个“广义的概念" 1. 表示一门学科 2. 表示一类软件,管理数据的软件 3. 表示某一个具体的数据库软件 4. 表示部署了某个数据库软件的主机(电脑) 本专栏介绍的是具体的数据库软件:MySQL 数据库软件的主要功能是对数据的增删…...
Spring XML 配置
Spring XML 配置是 Spring Framework 的传统配置方式,通过 XML 文件定义 Bean、依赖注入、AOP 等核心功能。以下是详细的 Spring XML 配置解析: 一、基础配置 1. XML 配置文件结构 <?xml version"1.0" encoding"UTF-8"?> …...
AI数字人:品牌营销的新宠与增长密码(6/10)
摘要:AI数字人凭借低成本、高可控性与强互动性等优势,正成为品牌营销新宠。通过技术驱动,AI数字人从虚拟形象发展为智能交互的数字化身,广泛应用于直播、客服、内容生产等营销场景,助力品牌提升营销效果与用户互动体验…...
CentOS笔记本合上盖子不休眠
通过修改 /etc/systemd/logind.conf 文件中的 HandleLidSwitch 和 HandleLidSwitchDocked 设置为 ignore,可以实现合上笔记本盖子时不休眠的效果。如果有其他电源管理工具或桌面环境的设置干扰,也需要一并调整。 // 切换到root用户 su root// logind.co…...
Vue.js 之 `v-for` 命令详解
Vue.js 之 v-for 命令详解 在 Vue.js 中,v-for 是一个非常强大的指令,用于遍历数组或对象中的数据,并渲染相应的 DOM 元素。无论是在列表展示、表单生成还是动态组件加载中,v-for 都发挥着重要作用。本文将详细介绍 v-for 的用法…...
Linux命令-pidstat
pidstat命令是一个用于监控系统中各个进程活动的性能监控工具。它能够实时输出每个进程的 CPU、内存、I/O 等关键性能指标。以下是关于 pidstat 命令的详细介绍: 语法 pidstat [选项] [时间间隔] [次数]常用选项 -h 或 --help :显示帮助信息。 -v &…...
map和set
1.序列式容器和关联式容器 在认识map和set之前,关于容器,有两个重要的分类 序列式容器关联式容器 序列式容器:按照元素插入的顺序保存数据,关注元素的顺序和位置,因为逻辑结构为线性序列的数据结构,两个位…...
CentOS 6.9 安装 Zabbix 3.0 详细教程
一、引言 在 Linux 环境下,有许多实用的系统监控软件,如 Nagios、Cacti、Zabbix、Monit等。这些开源软件能帮助我们更好地管理机器,及时发现问题并警告系统维护人员。今天我们将重点研究 Zabbix,使用它的目的是为了更好地监控MySQ…...
通俗的理解TCP的三次握手四次挥手
前言 本文是博主根据自身理解,尽量用最通俗的形式解释TCP的三次握手四次挥手。 一、三次握手:为什么不是两次或四次? 1. 三次握手过程 SYN:客户端发送SYN1, seqx(我要连接)SYNACK:服务器回复…...
【Python进阶】正则表达式实战指南:从基础到高阶应用
目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比 二、实战演示环境配置要求核心代码实现案例1:邮箱格式验证案例2:提取电话号码案例3:替换敏感信息 运行…...
linux下内存地址数学运算
如下代码计算地址并16字节对齐: char* buffer (char*)malloc(a3 0x1000);unsigned long long tmp (((unsigned long long)buffer 0x10) & 0xffffffffffffff00);char* buf (char*)tmp;假如把地址当作整数,加减程序运算,直接转换是不行…...