【C++练级之路】【Lv.8】【STL】list类的模拟实现

文章目录
- 引言
- 一、结点
- 二、迭代器
- 2.1 成员变量与默认成员函数
- 2.2 operator*
- 2.3 operator->
- 2.4 operator++
- 2.5 operator- -
- 2.6 relational operators
- 三、list
- 3.1 成员变量
- 3.2 迭代器
- 3.2.1 begin
- 3.2.2 end
- 3.3 默认成员函数
- 3.3.1 constructor
- 3.3.2 destructor
- 3.3.3 copy constructor
- 3.3.4 operator=
- 3.4 修改
- 3.4.1 insert
- 3.4.2 push_front
- 3.4.3 push_back
- 3.4.4 erase
- 3.4.5 pop_front
- 3.4.6 pop_back
- 3.4.7 clear
- 3.4.8 swap
- 总结
引言
因为list结构的特殊性,所以拆分为结点、迭代器和list本身进行学习。
一、结点
细节:
- 使用struct,标明公有属性(这样从外部调用比较方便)
- list是带头双向循环链表
- 提供全缺省的默认构造函数
template<class T>
struct __list_node
{__list_node<T>* _prev;__list_node<T>* _next;T _data;__list_node(const T& x = T()): _prev(nullptr), _next(nullptr), _data(x){}
};
二、迭代器
由于list的每个结点物理空间不连续,导致迭代器不能像之前string、vector那样简单的设计为指针,而是设计为一个类(进行封装),以此完成*、->、++、–等一系列操作。
2.1 成员变量与默认成员函数
细节:
- 仍然使用struct,标明公有属性
- 成员变量是一个结点的指针
- 提供带参构造函数(其余的默认成员函数不用显式定义,浅拷贝即可)
template<class T, class Ref, class Ptr>
struct __list_iterator
{typedef __list_node<T> node;typedef __list_iterator<T, Ref, Ptr> self;node* _node;__list_iterator(node* n): _node(n){}
};
此时的迭代器设计,可以说是list乃至STL的精华,天才般地运用了类的优势。
2.2 operator*
细节:
- 返回引用,为了区别普通迭代器和const迭代器
Ref operator*()
{return _node->_data;
}
2.3 operator->
细节:
- 返回指针,为了区别普通迭代器和const迭代器
Ptr operator->()
{return &_node->_data;
}
2.4 operator++
细节:
- 为了区分前置和后置,后置参数加上int(无实际意义,以示区分)
- 前置传引用返回,后置传值返回
self& operator++()//前置++
{_node = _node->_next;return *this;
}self operator++(int)//后置++
{self tmp(*this);_node = _node->_next;return tmp;
}
2.5 operator- -
细节:同上
self& operator--()//前置--
{_node = _node->_prev;return *this;
}self operator--(int)//后置--
{self tmp(*this);_node = _node->_prev;return tmp;
}
2.6 relational operators
bool operator!=(const self& s)
{return _node != s._node;
}bool operator==(const self& s)
{return _node == s._node;
}
三、list
3.1 成员变量
list类包含了
- _head(指向哨兵位)
template<class T>
class list
{
public:typedef __list_node<T> node;
private:node* _head;
};
3.2 迭代器
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;

3.2.1 begin
细节:
- begin()在_head->next
- 使用匿名对象
iterator begin()
{return iterator(_head->_next);
}const_iterator begin() const
{return const_iterator(_head->_next);
}
3.2.2 end
细节:
- end()在_head
- 使用匿名对象
iterator end()
{return iterator(_head);
}const_iterator end() const
{return const_iterator(_head);
}
3.3 默认成员函数
3.3.1 constructor
空初始化:创建哨兵位
void empty_init()
{_head = new node;_head->_prev = _head;_head->_next = _head;
}
无参构造
list()
{empty_init();
}
迭代器区间构造
细节:使用类模板,可以传任意类型的迭代器
template <class InputIterator>
list(InputIterator first, InputIterator last)
{empty_init();while (first != last){push_back(*first);++first;}
}
3.3.2 destructor
~list()
{clear();delete _head;_head = nullptr;
}
3.3.3 copy constructor
现代写法
细节:
- 用迭代器区间构造,构造出临时对象
- 再使用list中的swap,交换*this和tmp的值,完成拷贝构造
list(const list<T>& lt)
{empty_init();list<T> tmp(lt.begin(), lt.end());swap(tmp);
}
3.3.4 operator=
现代写法
细节:
- 传参变成传值,这样就会拷贝构造出一个临时对象
- 再使用list中的swap,交换*this和tmp的值,完成赋值重载
list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}
3.4 修改
3.4.1 insert
指定位置插入
细节:
- 在pos之前插入
- 迭代器不会失效
void insert(iterator pos, const T& x)
{node* cur = pos._node;node* prev = cur->_prev;node* new_node = new node(x);prev->_next = new_node;new_node->_prev = prev;cur->_prev = new_node;new_node->_next = cur;
}
3.4.2 push_front
头插
void push_front(const T& x)
{insert(begin(), x);
}
3.4.3 push_back
尾插
void push_back(const T& x)
{insert(end(), x);
}
3.4.4 erase
指定位置删除
细节:
- assert断言,防止删除哨兵位
- 返回删除节点的下一位,防止迭代器失效
iterator erase(iterator pos)
{assert(pos != end());node* cur = pos._node;node* prev = cur->_prev;node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;return iterator(next);
}
3.4.5 pop_front
void pop_front()
{erase(begin());
}
3.4.6 pop_back
void pop_back()
{erase(--end());
}
3.4.7 clear
清除所有结点(除哨兵位以外)
void clear()
{iterator it = begin();while (it != end()){erase(it++);}
}
3.4.8 swap
交换两个list类的值
细节:使用std库中的swap函数,交换各个成员变量的值
void swap(list<T>& lt)
{std::swap(_head, lt._head);
}
总结
学习完list类,对于STL中的精华——迭代器设计,有了更深一步的了解。同时,了解多参数模板的用途和方法,极大提高代码复用程度。

相关文章:
【C++练级之路】【Lv.8】【STL】list类的模拟实现
快乐的流畅:个人主页 个人专栏:《C语言》《数据结构世界》《进击的C》 远方有一堆篝火,在为久候之人燃烧! 文章目录 引言一、结点二、迭代器2.1 成员变量与默认成员函数2.2 operator*2.3 operator->2.4 operator2.5 operator- …...
【右一的电子笔记】全导航,持续更新...
文章目录 📚计算机基础🐇高程(c)🐇python基础🐇数据结构🐇数据库系统概念🐇计算机网络🐇计算机组成原理🐇操作系统 📚大数据🐇大数据管…...
关于前端的console的方法的收集
console的常用方法列举 console.assert() 如果第一个参数为 false ,则将消息和堆栈跟踪记录到控制台。 console.clear() 清空控制台,并输出 Console was cleared。 console.count() 以参数为标识记录调用的次数,调用时在控制台打印标识…...
大工程 从0到1 数据治理 数仓篇(sample database classicmodels _No.7)
大工程 从0到1 数据治理 之数仓篇 我这里还是sample database classicmodels为案列,可以下载,我看 网上还没有类似的 案列,那就 从 0-1开始吧! 提示:写完文章后,目录可以自动生成,如何生成可参…...
phpcms v9敏感词内容替换
后台先在"扩展"——>"敏感词管理"中添加敏感词,然后修改phpcms\modules\content\content.php文件来实现添加或者编辑内容时敏感词的替换。(如果涉及会员投稿和留言等,也需要在对应模块中做类似处理) 在ad…...
浏览器---浏览器/http相关面试题
1.localStorage和sessionStorage 共同点:二者都是以key-value的键值对方式存储在浏览器端,大小大概在5M。 区别: (1)数据有效期不同:sessionStorage仅在当前浏览器窗口关闭之前有效;localStorag…...
java 中开源的html解析库Jsoup 简单例子
下面是一个使用Jsoup库解析HTML的简单Java例子。这个例子展示了如何使用Jsoup从一个HTML字符串中提取数据。 首先,确保你已经将Jsoup作为依赖项添加到你的项目中。如果你使用的是Maven,可以在pom.xml文件中添加以下依赖: &…...
Java程序中为什么要使用StringBuilder
遇到这个问题是来源于leetcode的一道题:字符串解码。其中的题解涉及字符串的操作使用的是StringBuilder,不是String。 class Solution {public String decodeString(String s) {StringBuilder res new StringBuilder();int multi 0;LinkedList<Int…...
【软件架构】02-复杂度来源
1、性能 1)单机 受限于主机的CPU、网络、磁盘读写速度等影响 在多线程的互斥性、并发中的同步数据状态等; 扩展:硬件资源、增大线程池 2)集群 微服务化拆分,导致调用链过长,网络传输的消耗过多。 集…...
怎样让MCU/SFU视频会议ovmedia 接入GB28281监控视频参会互动
在国内视频应用对GB监控接入是常规操作,很多系统需要接入监控视频交互处理。我们以ovmedia视频会议为例做一个接入互动。 GB28181协议在流媒体系统较为普及,我们以开源SRS系统对接监控端再接入会议(也可以用商用GB流平台,操作基本…...
Spring Boot打war包部署到Tomcat,访问页面404 !!!
水善利万物而不争,处众人之所恶,故几于道💦 文章目录 Spring Boot打war包部署到Tomcat,访问页面404 !!!解决办法:检查Tomcat版本和Jdk的对应关系,我的Tomcat是6.x&#x…...
Docker Desktop 4.27.1 Windows 10 安装 教程
Docker Desktop 4.27.1 Windows 10 安装 版本要求windows 版本要求wsl 版本要求docker desktop 版本 安装首先确保系统版本符合要求前提下安装wsl安装 Dockers Desktop安装说明 安装问题docker Desktop 无法正常启动,提示wsl 相关信息wsl --install 执行输出帮助日志…...
【ARMv8M Cortex-M33 系列 8 -- RT-Thread 移植 posix pthread】
文章目录 RT-Thread POSIX PthreadRT-Thread Pthread 相关宏定义RT-Thread libc 初始化RT-Thread Pthread 测试 RT-Thread POSIX Pthread pthread是POSIX(Portable Operating System Interface)标准定义的一套线程相关的API,全称为POSIX Thr…...
fastApi笔记08-Cookie和Header
Cookie 可以像Query,Path,Body等同样的方式来定义Cookie参数 from typing import Annotatedfrom fastapi import Cookie, FastAPIapp FastAPI()app.get("/items/") async def read_items(ads_id: Annotated[str | None, Cookie()] None):r…...
解决pycharm中PIL安装失败
问题:在调用pil时显示pil标红 我在设置中下载每次失败,显示 ERROR: Could not find a version that satisfies the requirement PIL (from versions: none) ERROR: No matching distribution found for PIL我尝试了很久,查看了一些博客 &a…...
数据结构哈希表
这里个大家用数组来模拟哈希表 法一:拉链法 法二:开放寻址法 /** Project: 11_哈希表* File Created:Sunday, January 17th 2021, 2:11:23 pm* Author: Bug-Free* Problem:AcWing 840. 模拟散列表 拉链法*/ #include <cstring> #include <iostr…...
[C#]winform使用引导APSF和梯度自适应卷积增强夜间雾图像的可见性算法实现夜间雾霾图像的可见度增强
【算法介绍】 提升夜间雾霾图像可见度的技术研究:引导APSF与梯度自适应卷积的应用 随着城市化的快速发展,雾霾现象日益严重,尤其是在夜间,雾霾对图像的可见度造成了极大的影响。因此,提升夜间雾霾图像的可见度成为了…...
【Django】Django自定义后台表单——对一个关联外键对象同时添加多个内容
以官方文档为例: 一个投票问题包含多个选项,基本的表单设计只能一个选项一个选项添加,效率较低,如何在表单设计中一次性添加多个关联选项? 示例代码: from django.contrib import adminfrom .models impo…...
迷茫?没有努力的方向?没有耐心去坚持?精选书籍推荐2
迷茫书籍推荐 在渡过自卑期后,下一阶段就是迷茫期,我就是典型。坚持考研失败,然后工作上不顺利,尽管稍稍改变了自卑,但是却因为从前的失败,对下一步何去何从产生了迷茫。这也是我这篇文章希望帮助大家解决的…...
MySQL报错:sql_mode=only_full_group_by解决方法
Linux环境 ubuntu 22.04 MySQL是8.0.35版本 问题描述 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column auth_system.t_class_temp_config.id which is not functionally dependent on columns in GROUP BY clause; this is inco…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
