STL库中list的迭代器实现痛点分析
前文
本篇文章准备换个模式,之前都是先详解模拟实现,但是模拟实现的基本逻辑大多数老铁都是明白的,所以我们这次主要讲解STL库中list的独特性,也就是模拟实现中的重难点
文末有模拟实现的源码
一,list实现的特殊类
list实现和前面vector,string最大的区别莫过于单独封装了迭代器。
我们通常使用的迭代器分为两种:1.原生指针作为迭代器。如vector,string。2.自定义类型对原生指针进行封装,模拟指针的行为。如list。
vector:

list:

在list中,我们对原生指针进行封装,模拟指针的行为,因此我们需要在该类中实现*(),->,前置++,后置++,前置--,后置--,!=,==等函数重载
这时候可能有的老铁对,迭代器模板中三个模板参数感到惊讶,下面我们就来讲解一下。
二,迭代器模板中的多个模板参数

如图,迭代器模板参数中定义了三个模板参数,这是为什么呢?要注意这里是list中模板非常非常巧妙的一种用法。
第一个T就不用多说了,和vector中的模板参数意义一样。我们重点说第二和第三个.
2.1 Ref模板参数
Ref模板参数的产生主要是因为*()操作符重载

在实际的应用中,我们的list可能会被const修饰,导致里面的值只能读取不能修改,而如果用第一个模板参数我们则无法实现 const修饰返回值,因此我们专门写了第二个模板参数Ref来应对这种情况。

如上图所示,右边const修饰的list其中的值无法改变,我们会直接调用const_iterator迭代器进行模板实例化,这样Ref的值就为const T&,至此,我们就借助了第二个模板参数实现了正常迭代器和const修饰的迭代器的区分.
2.2 Ptr模板参数
Ptr模板参数是专门给->操作符重载准备的.

没有Ptr的话应该是这样

我们多一个模板参数的原因和Ref的原因一样,都是为了应对list被const修饰无法改变的情况
但是list迭代器中->操作符重载有一个重要的特性。如下所示


图中第313行和314行代码不一样但执行效果却一样,为什么呢?
根据语法,313行想访问_a1,应该这样写it->->_a1,但it->_a1却也可以,为什么呢?
这是因为在这里我们为了增强可读性,省略了一个->。
三,源码
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
namespace mjw
{template<class T>struct list_node{list_node<T>* _prev;list_node<T>* _next;T _data;list_node(const T& val=T()):_prev(nullptr),_next(nullptr),_data(val){}};template<class T,class Ref,class Ptr>struct _list_iterator{typedef list_node<T> node;typedef _list_iterator<T, Ref,Ptr> iterator;node* _node;_list_iterator(node* n):_node(n){}//*()重载Ref operator*(){return _node->_data;}//->重载T* operator->(){return &_node->_data;}//前置++iterator& operator++(){_node = _node->_next;return *this;}//后置++iterator operator++(int){iterator tmp(*this);_node = _node->_next;return tmp;}//前置--iterator& operator--(){_node = _node->_prev;return *this;}//后置--iterator operator--(int){iterator tmp(*this);_node = _node->_prev;return tmp;}//!=重载bool operator!=(const iterator ls){return _node != ls._node;}//==重载bool operator==(const iterator ls){return _node == ls._node;}};template<class T>class list{public:typedef list_node<T> node;typedef _list_iterator<T,T&,T*> iterator;typedef _list_iterator<T,const T&,const T*> const_iterator;void empty_init(){_head = new node;_head->_next = _head;_head->_prev = _head;}//构造list(){empty_init();}//区间构造//先初始化,然后一个一个尾插template<class InputIterator>list(InputIterator first, InputIterator last){empty_init();while (first != last){push_back(*first);++first;}}void swap(list<T>& tmp){std::swap(_head, tmp._head);}//拷贝构造list(const list<T>& lt){empty_init();list<T> tmp(lt.begin(),lt.end());swap(tmp);}//赋值list<T>& operator=(list<T> lt){swap(lt);return *this;}//析构~list(){delete _head;_head = _head->_next = _head->_prev = nullptr;}//clearvoid clear(){iterator cur = begin();while (cur != end()){erase(cur++);}}//begin()iterator begin(){return iterator(_head->_next);}const_iterator begin() const{return const_iterator(_head->_next);}//end()iterator end(){return iterator(_head);}const_iterator end() const{return const_iterator(_head);}//尾插void push_back(const T& val){/*node* newnode = new node(val);node* next = _head;node* prev = _head->_prev;newnode->_next = next;newnode->_prev = prev;prev->_next = newnode;next->_prev = newnode;*/insert(end(), val);}//尾删void pop_back(){erase(--end());}//头插void push_front(const T& val){insert(begin(), val);}//头删void pop_front(){erase(begin());}void insert(iterator pos, const T& val){node* newnode = new node(val);node* next = pos._node;node* prev = next->_prev;newnode->_next = next;newnode->_prev = prev;prev->_next = newnode;next->_prev = newnode;}//为了防止迭代器失效,返回要删除的迭代器的下一个数据iterator erase(iterator pos){assert(pos._node != _head);node* prev = pos._node->_prev;node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;pos._node = nullptr;return iterator(next);}private:node* _head;};}
相关文章:

STL库中list的迭代器实现痛点分析
前文本篇文章准备换个模式,之前都是先详解模拟实现,但是模拟实现的基本逻辑大多数老铁都是明白的,所以我们这次主要讲解STL库中list的独特性,也就是模拟实现中的重难点文末有模拟实现的源码一,list实现的特殊类list实现…...

字符编码对比(GBK、Unicode、UTF-8)
摘要我们在网上能看到各种文字和符号,那么它们是怎么存储和转化的,还有我们常常提及的UTF-8,为什么都要设置这种编码方式,这里就探讨下。字符集字符集:就是各国文字、符号、数字的集合。常见的字符集有:ASC…...

【百面成神】Redis基础11问,你能坚持到第几问
前 言 🍉 作者简介:半旧518,长跑型选手,立志坚持写10年博客,专注于java后端 ☕专栏简介:纯手打总结面试题,自用备用 🌰 文章简介:Redis最基础、重要的11道面试题 文章目录…...

十大排序算法极简汇总篇
说明 十大排序算法可以说是每个程序员都必须得掌握的了,如果你们像从 0 详细学习每一篇,那么你们可以看前面的文章。 但是呢,有些人可能已经学过,想要快速复习一下,看看代码怎么写的,那么可以看这篇十大排…...

数据结构笔记
文章目录第一章:数据结构与算法第二章:稀疏数组和队列一 、稀疏sparsearray 数组(一)案例需求(二)稀疏数组介绍(三)应用实列(四)代码实现二、队列(…...

web前端框架——Vue的特性
目录 前言: 一.vue 二.特性 1.轻量级 2.数据绑定 3.指令 4.插件 三.比较Angular 、React 、Vue 框架之间的比较 1. Angular Angular的优点: 2. React React 的优点: 3.vue 3.Vue的优点: 前言: 本篇文章…...

提权工具推荐(PEASS-ng、linpeas_linux_amd64、winPEASany_ofs)
介绍 在这里,您可以找到适用于Windows、Linux/Unix*和MacOS的权限提升工具。 这些工具搜索您可以利用的可能的本地权限提升路径,并用漂亮的颜色打印给您,这样您就可以很容易地识别错误配置。 查看book.hacktricks.xyz中的本地Windows权限提升检查表WinPEAS-Windows本地权限…...

Spark - 继承 FileOutputFormat 实现向 HDFS 地址追加文件
目录 一.引言 二.源码浅析 1.RDD.saveAsTextFile 2.TextOutputFormat 3.FileOutputFormat 三.源码修改 1.修改文件生成逻辑 - getRecordWriter 2.允许目录存在 - checkoutputSpecs 3.全部代码 - TextOutputFormatV2 四.追加存储代码实战 五.总结 一.引言 Output d…...

树莓派编程控制继电器及继电器组
目录 一,继电器说明 ● 继电器接口说明 ① 继电器输入端: ② 继电器输出端: 二,树莓派控制继电器 三,树莓派控制继电器组 一,继电器说明 通俗点讲,可以把继电器理解成是一些功能设备的控制开关。 ● LOW&#…...
oracle和mysql的区别
Oracle与MySQL的区别以及优缺点 MySQL的特点 1、性能卓越,服务稳定,很少出现异常宕机; 2、开放源代码无版本制约,自主性及使用成本低; 3、历史悠久,社区和用户非常活跃,遇到问题及时寻求帮助…...

<Linux开发> linux应用开发-之-uart通信开发例程
一、简介 串口全称叫做串行接口,串行接口指的是数据一个一个的按顺序传输,通信线路简单。使用两条线即可. 实现双向通信,一条用于发送,一条用于接收。串口通信距离远,但是速度相对会低,串口是一种很常用的工…...

基于深度学习的安全帽检测系统(YOLOv5清新界面版,Python代码)
摘要:安全帽检测系统用于自动化监测安全帽佩戴情况,在需要佩戴安全帽的场合自动安全提醒,实现图片、视频和摄像头等多种形式监测。在介绍算法原理的同时,给出Python的实现代码、训练数据集,以及PyQt的UI界面。安全帽检…...

Linux - 进程控制(进程替换)
0.引入创建子进程的目的是什么?就是为了让子进程帮我执行特定的任务让子进程执行父进程的一部分代码如果子进程想执行一个全新的程序代码呢? 那么就要使用进程的程序替换为什么要有程序替换?也就是说子进程想执行一个全新的程序代码ÿ…...
Java中 ==和equals的区别是什么?
作用: 基本类型,比较值是否相等引用类型,比较内存地址值是否相等不能比较没有父子关系的两个对象equals()方法的作用: JDK 中的类一般已经重写了 equals(),比较的是内容自定义类如果没有重写 equals(),将…...

Linux(网络基础---网络层)
文章目录0. 前言1. IP协议1-1 基本概念1-2 协议头格式2. 网段划分2-1 基本概念2.2 IP地址分五大类2-3 特殊的IP地址2-4 IP地址的数量限制2-5 私有IP地址和公网IP地址2-6 路由0. 前言 前面我们讲了,应用层、传输层;本章讲网络层。 应用层:我…...

空间信息智能应用团队研究成果介绍及人才引进
目录1、多平台移动测量技术1.1 车载移动测量系统1.2 机载移动测量系统2、数据处理与应用技术研究2.1 点云与影像融合2.2 点云配准与拼接2.3 点云滤波与分类2.4 道路矢量地图提取2.5 道路三维自动建模2.6 道路路面三维病害分析2.7 多期点云三维变形分析2.8 地表覆盖遥感监测分析…...

ChatGPT应用场景与工具推荐
目录 写在前面 一、关于ChatGPT 二、应用实例 1.写文章 2.入门新的知识 3.解决疑难问题 4.生成预演问题 5.文本改写 6.语言翻译 7.思维导图 8.PDF阅读理解 9.操作格式化的数据 10.模拟场景 11.写代码 三、现存局限 写在前面 本文会简单介绍ChatGPT的特点、局限以…...

图像分类卷积神经网络模型综述
图像分类卷积神经网络模型综述遇到问题 图像分类:核心任务是从给定的分类集合中给图像分配一个标签任务。 输入:图片 输出:类别。 数据集MNIST数据集 MNIST数据集是用来识别手写数字,由0~9共10类别组成。 从MNIST数据集的SD-1和…...

艹,终于在8226上把灯点亮了
接上次点文章ESP8266还可以这样玩这次,我终于学会了在ESP8266上面点亮LED灯了现在一个单片机的价格是几块,加上一个晶振,再来一个快递费,十几块钱还是需要的。所以能用这个ESP8266来当单片机玩,还是比较不错的可以在ub…...

脱不下孔乙己的长衫,现代的年轻人该怎么办?
“如果我没读过书,我还可以做别的工作,可我偏偏读过书” “学历本该是我的敲门砖,却成了我脱不下的长衫。” 最近,“脱下孔乙己的长衫”在网上火了。在鲁迅的原著小说中,孔乙己属于知识阶级(长衫客…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...