当前位置: 首页 > news >正文

C++ list模拟实现

文章里用到查询C++的网址为:cplusplus.com - The C++ Resources Network

源代码是stl30.tar.gz


目录

前言

一、成员变量

二、构造函数

三、push_back()

四、迭代器

(1)普通迭代器

(2)const迭代器

(3)迭代器失效

五、insert

六、erase,pop_back,pop_front

七、operator->

八、析构函数,拷贝构造函数,赋值重载,clear,swap


前言

我们list的实现依旧先从源代码入手,我们需要搞清楚部分的逻辑,这样方便我们去模拟实现。

link_type是节点的指针。接着我们去观察一下无参的初始化。

这里弄得是哨兵位的节点。get_node是在内存池申请内存,类似malloc申请空间不初始化。

接着我们来浅浅的观察一下push_back。某个位置前面插入。

所以其实我们明白链表的结构,很多都能够大概猜测出来。

一、成员变量

首先链表我们需要定义一个节点,只是我们这里需要用模板来实现。

还需要完成构造函数。

接着就完成成员变量的创建。(typedef只是为了写代码简单一点)

二、构造函数

我们先完成无参的构造函数,源代码中是用内存池,但我们这里简单实现一下,new也是动态开辟的空间。

这里我们再实现简单的size()和empty()。

三、push_back()

push_back逻辑上也很简单,因为是双向循环链表,我们需要先创建一个新节点,然后把新节点的尾指针指向哨兵位,旧的尾节点的下一个指针指向新的节点,新节点的头指针也要指向旧节点,哨兵位的头指针指向新节点。

四、迭代器

(1)普通迭代器

迭代器我们就不能单纯使用原生指针来,因为list两个节点之间物理上没有联系,我们加加也不会到下一个节点去。所以我们先观察一下源代码里面是怎么实现的。

重载了解引用返回节点数据。

也重载了++。

我们链表做不到vector和string结构的连续,但是我们list有着下一个节点的地址,所以我们可以用类型对节点指针进行封装来实现。我们就可以定义struct迭代器,struct默认公有,class则默认是私有。

这样我们完成了对自己list迭代器的封装,我们就可以去实现迭代器的begin()等等。

(2)const迭代器

我们要分清楚const iterator是迭代器本身不能修改,而我们要模拟实现的是const_iterator是指向内容不能修改。

但我们这样复制过来一个类,有点复杂了,我们先来看看库里面是怎么实现的呢?

但在编译后其实本质是相同的,一个是我们自己实现的,一个是通过类模板让编译器实例化出两个不同的类。

(3)迭代器失效

我们能够发现在list中,我们跟之前vector相似的代码,却不会发生迭代器失效。因为vector会挪动数据,而list位置不是连续的,在这种情况不会失效。

那在什么情况会发生迭代器失效呢?在删除一个节点,如果不重置的话,就相当于访问野指针了。

五、insert

insert是在pos位置插入数据。所以要拿到当前位置和前一个位置的节点,然后去更改两个位置的指向关系,将新的节点指向关系理清楚就很容易模拟实现出insert了。 

完成了insert其实我们可以不用自己再实现push_back()和push_front()的,只需要对insert进行复用。

六、erase,pop_back,pop_front

删除pos位置也很简单,就是找到前一个位置和后一个位置,然后将它们链接起来就可以了。​​​​​​​注意要返回删除位置下一个的。

这样我们依旧可以复用erase来实现头删和尾删。

七、operator->

为什么operator->是这样实现呢,为什么返回T*呢,其实这里为了可读性省略了一个->,我们可以详细写出来,这样会比较清晰。

八、析构函数,拷贝构造函数,赋值重载,clear,swap

析构函数我们进行对clear的复用就可以了。

拷贝构造函数我们需要注意我们不能单纯的循环尾插,因为链表并没有构造出哨兵位的头节点,所以我们刚好可以实现一个空链表的初始化来复用。

接着我们来验证一下拷贝构造。

对于赋值重载我们依旧使用现代写法也就是复用库里面的swap。

http://www.dtcms.com/a/330046.html

相关文章:

  • 未来AI:微算法科技(NASDAQ:MLGO)开发基于忆阻器网络储层计算MemristorPattern虚拟平台
  • 精准阻断内网渗透:联软科技终端接入方案如何“锁死”横向移动?
  • 科技赋能虚拟形象:3D人脸扫描设备的应用与未来
  • 钻井泥浆搅拌机的设计cad1张三维图+设计说明书
  • ULN2003与ULN2803的区别
  • MySQL优化常用的几个方法
  • 0813 网络编程基础
  • docker 容器内编译onnxruntime
  • cisco无线WLC flexconnect配置
  • 【Virtual Globe 渲染技术笔记】4 椭球面上的曲线
  • 大数据可视化设计 | 智能家居 UI 设计:从落地方法到案例拆解
  • 室外 3DVG 基准
  • mysql - 查询重复数据,不区分大小重复问题解决
  • Redis的基础命令
  • 玳瑁的嵌入式日记D17-08013(linux)
  • Java多线程进阶-从乐观锁到读写锁
  • 项目可手撕题目详解
  • 【数字孪生系列】数字孪生引擎中的地标建筑管理系统
  • rar压缩包python解压
  • Go语言网络故障诊断与调试技巧:从入门到实战
  • AMD KFD的BO设计分析系列 0:开篇
  • redis分布式锁封装 redis分布式锁实现 封装Spring工具Redis工具类 redis操作类封装 redis锁封装 redis分布式锁封装
  • 【SpringBoot系列-02】自动配置机制源码剖析
  • Promise.all使用
  • 嵌入式Linux中的OpenWrt 是指什么
  • python类--python011
  • Python3解释器深度解析与实战教程:从源码到性能优化的全路径探索
  • O2OA:数字化转型中安全与效率的平衡之道
  • hadoop 前端yarn 8088端口查看任务执行情况
  • 华清远见25072班C语言学习day8