前言
在掌握 list 基本用法后,我们深入其底层实现。本文将重点分析双向链表容器的常用接口及其核心逻辑。
一、list 的成员变量
list 的底层数据结构是双向链表,通常包含一个哨兵节点(Sentinel Node)来简化边界处理。通过三个主要结构体和类来实现:
- struct list_node:存储链表结点信息。
- struct list_iterator:封装结点指针,支持运算符重载以访问结点。
- class list:实现双向链表的各种增删查改操作。
1.1 结构体 list_node
template<class T> struct list_node {
typedef list_node<T> Node;
T _data; // 链表存储的节点值
Node* _prev; // 前驱指针
Node* _next; // 后继指针
};
每个结点包含数据域和前后指针。为了代码简洁,通常将 list_node 重命名为 Node。
1.2 结构体 list_iterator
迭代器是对结点指针的封装,使其行为像指针一样。
template<class T, class Ref, class Ptr>
struct list_iterator {
typedef list_node<T> Node;
typedef list_iterator< T, Ref, Ptr> Self;
Node* _pnode;
};
这里使用了模板参数 Ref 和 Ptr,目的是仅用一个类模板同时生成普通迭代器和常量迭代器,避免代码重复:
- T:接收容器中实际存储的元素类型。
- Ref:决定解引用操作符
operator*()的返回类型(如T&或const T&)。 - Ptr:决定箭头操作符
operator->()的返回类型(如T*或const T*)。
1.3 类 class list
template<class T> {
:
list_node<T> Node;
list_iterator<T, T&, T*> iterator;
list_iterator<T, T&, T*> const_iterator;
:
Node* _head;
};


