接下来我会依照前面所说的一些接口以及list的结构来进行讲解。

1. list_node的结构

1.1 list_node结构体

list由于其结构为双向循环链表,所以我们在这里要这么初始化

  • _next:指向链表中下一个节点的指针
  • _prev:指向链表中上一个节点的指针
  • _val:存储节点的值

list_node(const T& val = T()) 用于初始化节点,将 _next 和 _prev 指针默认设置为 nullptr,并将 _val 初始化为传入的值

struct list_node
{list_node<T>* _next;list_node<T>* _prev;T _val;list_node(const T& val = T()):_next(nullptr), _prev(nullptr), _val(val){}
};
  1. typedef list_node<T> Node;

    • list_node<T>(链表节点类型)简化定义为Node
    • 在类内部可以直接使用Node来表示链表节点类型,无需重复写list_node<T>
  2. typedef _list_iterator<T, T&, T*> iterator;

    • 定义了普通迭代器类型iterator
    • 这里的_list_iterator应该是一个迭代器模板类,三个模板参数分别表示:
      • 存储的数据类型T
      • 迭代器解引用后返回的引用类型T&
      • 迭代器解引用后返回的指针类型T*
  3. typedef _list_iterator<T, const T&, const T*> const_iterator;

    • 定义了常量迭代器类型const_iterator
    • 与普通迭代器的区别是,解引用后返回的是const类型的引用和指针
    • 用于对const list对象进行遍历,保证不能通过迭代器修改元素值
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;
};

1.2 list和list_node分离设计原因 

list_node结构体和list类分离设计,是一种典型的 "数据存储" 与 "逻辑管理" 分离的思想。

1. 职责分离,符合单一职责原则
  • list_node结构体:仅负责存储单个节点的数据连接关系(前驱_prev、后继_next指针),它的职责非常单一 —— 就是作为链表的 "最小数据单元"。
  • list:负责管理整个链表的逻辑,包括节点的创建 / 销毁、插入 / 删除、遍历、容量管理等操作。它不直接存储数据,而是通过操作list_node对象来实现链表的整体功能。

这种分离让代码更清晰:节点只关心自身数据和连接,链表类只关心整体逻辑,便于维护和扩展。

2. 封装性更好,隐藏实现细节
  • list_node通常是list类的内部私有类型(或通过typedef限定在类内部使用),外部用户不需要知道节点的具体结构(比如_prev_next指针的存在)。
  • 用户只需通过list类提供的接口(如push_backerase、迭代器等)操作链表,无需直接接触节点,避免了误操作节点指针导致的内存问题(如野指针、内存泄漏)。
3. 便于迭代器设计和容器适配
  • 链表的迭代器需要通过节点的_next/_prev指针实现遍历,将节点封装为list_node后,迭代器可以统一通过节点指针操作,无需关心具体数据类型。
  • 符合 STL 容器的设计规范:STL 中所有容器都需要将 "元素存储" 和 "容器管理" 分离,这样才能统一迭代器接口。
  • list_node可以被视为一个通用的 "双向节点模板",如果未来需要实现其他基于双向节点的结构(如循环链表、队列等),可以复用list_node的设计。
  • 当需要扩展链表功能时,只需修改list类的管理逻辑,无需改动list_node的结构。

2. list迭代器

2.1 三个可变参数的原因

我们在这里之所以要设置三个,是因为在list的迭代器里面需要不同的类型。同时一个可变参数在一个类里面只会推导一次,所以我们在这里是需要是三个。

  • T:链表中存储的元素类型(如 intstring 等)。
  • Ref:迭代器解引用后返回的引用类型(普通迭代器用 T&,常量迭代器用 const T&)。
  • Ptr:迭代器通过 -> 运算符返回的指针类型(普通迭代器用 T*,常量迭代器用 const T*)。
template<class T,class Ref,class Ptr>
struct _list_iterator{typedef list_node<T> Node;typedef _list_iterator<T, Ref, Ptr> self;Node* _node;};

2.2 构造函数

我们在这里又会有构造函数,是因为我们在list中实际上写了三个类,一个list_iterator,一个list_node和一个list,这三者构成了完整的list。

这个就是在给list的迭代器进行初始化。因为是通过节点去访问所以怎么写。

_list_iterator(Node* node):_node(node)
{}

2.3 operator*()

返回对元素的引用Ref),模拟指针的解引用操作(如 *p 获取指针指向的对象)。所以在这里要使用Ref。

Ref operator*()
{return _node->_val;
}

2.4 operator->() 

这边的Ptr更多是为了结构体这种设计的,简单来说这样设计就是为了先进入结构体然后再访问其内部成员。

那为什么要加&呢?这是因为operator要返回一个指针,然后我们通过这个指针来访问结构体的内部成员。

Ptr operator->()
{return &_node->_val;
}

2.5 前置++

因为是前置的,所以是先++再return。

self 是迭代器类型本身(_list_iterator<T, Ref, Ptr>),它是一个 “指向元素的迭代器”,负责管理节点指针、提供遍历能力。

self& operator++()
{_node = _node->_next;return *this;
}

2.6 后置++

这边()里面的int是特殊处理,是为了和前置++构成函数重载。

又因为是后置++,所以我们让迭代器向后走并返回走之前的值。

self operator++(int)
{self tmp(*this);_node = _node->next;return tmp;
}

2.7 前置--

因为是前置--,所以先返回上一个节点在return。

self& operator--()
{_node = _node->_prev;return *this;
}

2.8 后置--

因为是后置--,所以先保存节点在--。

int是为了和前置--构成函数重载。

self operator--(int)
{self tmp(*this);_node = _node->_prev;return tmp;
}

2.9 operator!=

这个加const是防止修改指向和被指向的内容。

因为是bool类型的,所以直接比较两个指针的地址值是否一样即可。

bool operator!=(const self& it) const
{return _node != it._node;
}

2.10 operator==

这个加const是防止修改指向和被指向的内容。

因为是bool类型的,所以直接比较两个指针的地址值是否一样即可。

bool operator==(const self& it) const
{return _node == it._node;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/919830.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/919830.shtml
英文地址,请注明出处:http://en.pswp.cn/news/919830.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新能源汽车热管理仿真:蒙特卡洛助力神经网络训练

研究背景在新能源汽车的热管理仿真研究中&#xff0c;神经网络训练技术常被应用于系统降阶建模。通过这一方法&#xff0c;可以构建出高效准确的代理模型&#xff0c;进而用于控制策略的优化、系统性能的预测与评估&#xff0c;以及实时仿真等任务&#xff0c;有效提升开发效率…

第十九讲:C++11第一部分

目录 1、C11简介 2、列表初始化 2.1、{}初始化 2.2、initializer_list 2.2.1、成员函数 2.2.2、应用 3、变量类型推导 3.1、auto 3.2、decltype 3.3、nullptr 4、范围for 5、智能指针 6、STL的一些变化 7、右值引用和移动语义 7.1、右值引用 7.2、右值与左值引…

书写本体论视域下的文字学理论重构

在符号学与哲学的交叉领域&#xff0c;文字学&#xff08;Grammatologie&#xff09;作为一门颠覆性学科始终处于理论风暴的中心。自德里达1967年发表《论文字学》以来&#xff0c;传统语言学中"语音中心主义"的霸权地位遭遇根本性动摇&#xff0c;文字不再被视为语言…

为什么要做架构设计?架构设计包含哪些内容?

大家好,我是IT孟德,You can call me Aman(阿瞒,阿弥陀佛的ē,Not阿门的ā),一个喜欢所有对象(热爱技术)的男人。我正在创作架构专栏,秉承ITer开源精神分享给志同道合(爱江山爱技术更爱美人)的朋友。专栏更新不求速度但求质量(曹大诗人传世作品必属精品,请脑补一下《…

Vue2封装Axios

一、介绍Axios 是一个基于 promise 的 HTTP 库&#xff0c;简单的讲就是可以发送get、post等请求。二、安装npm install axios --save二、axios不同请求方式axios(config)这是 Axios 的核心方法&#xff0c;用于发送自定义配置的 HTTP 请求。通过传入一个包含请求配置的对象&am…

DataAnalytics之Tool:Metabase的简介、安装和使用方法、案例应用之详细攻略

DataAnalytics之Tool&#xff1a;Metabase的简介、安装和使用方法、案例应用之详细攻略 目录 Metabase的简介 1、特点 Metabase的安装和使用方法 1、安装 快速设置&#xff1a;开发环境 前端快速设置 后端快速设置 2、使用方法 Metabase的案例应用 Metabase的简介 Met…

frp v0.64.0 更新:开源内网穿透工具,最简洁教程

frp是一款跨平台的内网穿透工具&#xff0c;支持 Windows、macOS 与 Linux&#xff0c;它需要你有一台拥有固定公网 IP 的电脑&#xff0c;VPS 最好&#xff0c;然后就能愉快的进行内网穿透了。还支持 https&#xff0c;甚至可以用它进行小程序开发。Appinn v0.64.0 新增token…

【数据结构】B+ 树——高度近似于菌丝网络——详细解说与其 C 代码实现

文章目录B 树的定义B 树组织数据的方法往 B 树中插入键值对数据从 B 树中删除键值对把 B 树看作是 “真菌网络”——我理解并记忆 B 树的方法B 树的 C 代码实现初始化节点、B 树B 树节点内的二分查找B 树的数据插入操作B 树的删除数据操作范围查询与全局遍历销毁 B 树测试代码&…

01、数据结构与算法--顺序表

正式进入数据结构的学习&#xff0c;先从预备知识学起&#xff0c;戒焦戒躁戒焦戒躁...一、泛型的引入1、为什么需要泛型&#xff1f;先来看一个题目&#xff1a;实现一个类&#xff0c;类中包含一个数组成员&#xff0c;使得数组中可以存放任何类型的数据&#xff0c;也可以根…

8.23打卡 DAY 50 预训练模型+CBAM模块

DAY 50: 预训练模型与 CBAM 模块的融合与微调 今天&#xff0c;我们将把之前学到的知识融会贯通&#xff0c;探讨如何将 CBAM 这样的注意力模块应用到强大的预训练模型&#xff08;如 ResNet&#xff09;中&#xff0c;并学习如何高效地对这些模型进行微调&#xff0c;以适应我…

北极圈边缘生态研究:从数据采集到分析的全流程解析

原文链接&#xff1a;https://onlinelibrary.wiley.com/doi/10.1111/1744-7917.70142?afR北极圈边缘生态研究&#xff1a;从数据采集到分析的全流程解析简介本教程基于一项在俄罗斯摩尔曼斯克州基洛夫斯克市开展的长期生态学研究&#xff0c;系统讲解如何对高纬度地区特定昆虫…

Excel处理控件Aspose.Cells教程:使用Python将 Excel 转换为 NumPy

使用 Python 处理 Excel 数据非常常见。这通常涉及将数据从 Excel 转换为可高效操作的形式。将 Excel 数据转换为可分析的格式可能非常棘手。在本篇教程中&#xff0c;您将学习借助强大Excel处理控件Aspose.Cells for Python&#xff0c;如何仅用几行代码将 Excel 转换为 NumPy…

python 字典有序性的实现和OrderedDict

文章目录 一、Python 3.7+ 字典有序性的验证 二、如何在字典头部插入键值对 方法 1:创建新字典(推荐) 方法 2:使用 `collections.OrderedDict`(适合频繁头部插入场景) 方法 3:转换为列表操作(不推荐,效率低) 底层核心结构:双数组哈希表 有序性的实现原理 与旧版本(…

JVM 调优全流程案例:从频繁 Full GC 到百万 QPS 的实战蜕变

&#x1f525; JVM 调优全流程案例&#xff1a;从频繁 Full GC 到百万 QPS 的实战蜕变 文章目录&#x1f525; JVM 调优全流程案例&#xff1a;从频繁 Full GC 到百万 QPS 的实战蜕变&#x1f9e9; 一、调优本质&#xff1a;性能瓶颈的破局之道&#x1f4a1; 为什么JVM调优如此…

基于TimeMixer现有脚本扩展的思路分析

文章目录1. 加入数据集到data_loader.py和data_factory.py2. 参照exp_classification.py写自定义分类任务脚本&#xff08;如exp_ADReSS.py&#xff09;3. 接一个MLP分类头4. 嵌入指标计算、绘图、保存训练历史的函数5. 开始训练总结**一、可行性分析****二、具体实现步骤****1…

技术演进中的开发沉思-75 Linux系列:中断和与windows中断的区分

作为一名从 2000 年走过来的老程序员&#xff0c;看着 IT 技术从桌面开发迭代到微服务时代&#xff0c;始终觉得好技术就像老故事 —— 得有骨架&#xff08;知识点&#xff09;&#xff0c;更得有血肉&#xff08;场景与感悟&#xff09;。我想正是我的经历也促成了我想写这个…

【8位数取中间4位数】2022-10-23

缘由请输入一个8位的十进制整数&#xff0c;编写程序取出该整数的中间4位数&#xff0c;分别输出取出的这4位数以及该4位数加上1024的得数。 输入&#xff1a;一个整数。 输出&#xff1a;两个整数&#xff0c;用空格分隔-编程语言-CSDN问答 int n 0;std::cin >> n;std:…

mac电脑使用(windows转Mac用户)

首先&#xff0c;我们学习mac的键盘复制 command c 粘贴 command v 剪切 command xlinux命令行 退出中止 control c 退出后台 control d中英文切换大小写&#xff0c;按住左边向上的箭头 字母鼠标操作 滚轮&#xff1a;2个指头一起按到触摸板&#xff0c;上滑&#xff0c;…

项目中优惠券计算逻辑全解析(处理高并发)

其实这个部分的代码已经完成一阵子了&#xff0c;但是想了一下决定还是整理一下这部分的代码&#xff0c;因为最开始做的时候业务逻辑还是感觉挺有难度的整体流程概述优惠方案计算主要在DiscountServiceImpl类的findDiscountSolution方法中实现。整个计算过程可以分为以下五个步…

支持电脑课程、游戏、会议、网课、直播录屏 多场景全能录屏工具

白鲨录屏大师&#xff1a;支持电脑课程、游戏、会议、网课、直播录屏 多场景全能录屏工具&#xff0c;轻松捕捉每一刻精彩 在数字化学习、娱乐与办公场景中&#xff0c;高质量的录屏需求日益增长。无论是课程内容的留存、游戏高光的记录&#xff0c;还是会议要点的复盘、网课知…