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。

相关推荐
0xDevNull6 小时前
Java反射机制深度解析:从原理到实战
java·开发语言·后端
小小亮016 小时前
Next.js基础
开发语言·前端·javascript
ALex_zry6 小时前
C++网络编程心跳机制与连接保活:长连接稳定性保障
开发语言·网络·c++
Amumu121387 小时前
Js:正则表达式(二)
开发语言·javascript·正则表达式
学嵌入式的小杨同学7 小时前
STM32 进阶封神之路(三十二):SPI 通信深度实战 —— 硬件 SPI 驱动 W25Q64 闪存(底层时序 + 寄存器配置 + 读写封装)
c++·stm32·单片机·嵌入式硬件·mcu·架构·硬件架构
Sgf2277 小时前
ES8(ES2017)新特性完整指南
开发语言·javascript·ecmascript
好大哥呀7 小时前
C++ Web 编程
开发语言·前端·c++
ID_180079054737 小时前
小红书笔记评论 API,Python 调用示例与完整 JSON 返回参考
java·开发语言
Mr_Xuhhh8 小时前
LeetCode hot 100(C++版本)(上)
c++·leetcode·哈希算法
漫随流水8 小时前
c++编程:反转字符串(leetcode344)
数据结构·c++·算法