ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

C++ list容器模拟实现:迭代器、构造与STL风格编程

C++ list容器模拟实现:迭代器、构造与STL风格编程 list的模拟实现1.1 list基本结构list的结构是个带头双向循环链表每个数据是存储在一个单独的节点内这个节点除了存储数据还有两个指针分别指向前一个和后一个节点这里定义节点的类用struct定义list的类用class的原因是一个默认的共识一个类如果它的所有成员都不期望用访问限定符限制的时候习惯上就用struct定义这里的list_node通常作为链表的一个子结构是存储每个数据的一个最小单元链表内是要大量访问内部数据的所以这里不用访问限定符限制。虽然这样写后别人就可以随便访问这些结构了但是有迭代器之后在外层的角度是看不到节点的例如从使用的角度在接口使用的时候是不用链表的节点的无论是访问修改还是插入删除都是直接用迭代器的即虽然list_node是公有的但是其是一种隐形的封装平时看不到也不会/不需要访问这里 list_node T * _prev; 这个写法是C 模板语法 指针语法的组合list_node T 是语法规定 list_node是定义的模板结构体C 语法要求使用模板类 / 结构体时必须通过模板参数指定具体的泛型类型这里T是模板参数所以list_node T 是模板结构体的 “实例化类型写法”属于语法强制要求。*是语法规定*是 C 中 “指针类型” 的声明符号list_node T *表示 “指向list_node T 类型对象的指针”这是指针的标准语法。补充一下这里模板声明的作用范围模板声明的作用范围template class T 是 “模板参数声明”它的作用域仅限于紧跟在它后面的那个类或结构体、函数。例如代码语言javascriptAI代码解释// 第一个类模板list_node templateclass T // 作用范围下面的 struct list_node struct list_node { ... }; // 第二个类模板list templateclass T // 作用范围下面的 class list class list { ... };这里的两个 template class T 是独立的分别服务于 list_node 和 list 两个类彼此不影响。新类模板需要重新声明每个类模板都是独立的实体即使两个类的功能相关比如链表的节点和链表本身定义新的类模板时也必须重新写template class T 。原因是模板参数 T 是 “当前类模板的局部参数”只在当前类的范围内有效。比如 list_node 中的 T 和 list 中的 T 虽然名字相同但实际上是两个独立的模板参数只是习惯上用相同的字母表示。特殊情况嵌套类模板如果一个类模板内部嵌套了另一个类嵌套类可以直接使用外部类的模板参数无需重复声明代码语言javascriptAI代码解释templateclass T class outer { // 嵌套类直接使用外部的 T class inner { T data; // 这里的 T 继承自 outer 的 templateclass T }; };但如果嵌套类需要自己的独立模板参数比如同时支持 T 和 U则需要单独声明代码语言javascriptAI代码解释templateclass T class outer { // 嵌套类有自己的模板参数 U templateclass U // 单独声明作用范围下面的 inner class inner { T a; // 来自 outer 的 T U b; // 来自 inner 自己的 U }; };1.2 构造 尾插在这里插入图片描述尾插逻辑如图在这里插入图片描述在这里插入图片描述这里运行不了运行不了的原因是list_node 缺少无参构造函数 在 List.h 中list_node 结构体的构造函数只有带参数的版本list_node(const T x)但没有无参构造函数。 而在 list 类的构造函数中执行了 _head new Node; —— 这里尝试调用 list_node 的无参构造函数但该构造函数并不存在因此会触发编译错误。这里有三种解决办法方法 1利用list_node的带参构造显式传入默认值在 list 类的构造函数中创建头结点时显式调用 list_node 的带参构造并传入 T 类型的默认值通过 T() 触发 T 的默认构造也就是使用匿名对象T有可能是任意类型。这样无需为 list_node 新增无参构造函数。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表