深入理解list迭代器的设计与实现
引言
在STL容器中,list作为经典的双向链表容器,其迭代器设计体现了C++模板编程的精髓。本文将深入探讨如何从零开始设计一个符合STL规范的list迭代器,揭示其背后的设计哲学和技术细节。
1、链表基础结构
template <class T>
struct list_node {
T data_;
list_node<T>* next_;
list_node<T>* prev_;
list_node(const T& data = T())
: data_(data), next_(nullptr), prev_(nullptr) { }
};
每一个节点包含前驱指针、后继指针和数据元素,构成双向链表的基础单元。
2、链表迭代器的封装
list
不像vector
那样是一段连续的空间,方便通过直接通过+
、-
来计算地址位置,因此不能采用原生指针进行typedef
,需要将节点类型进行封装,通过运算符重载来达到移动“迭代器指针”。
2.1 初步封装迭代器类
template <class T>
struct __list_iterator {
typedef list_node<T> node;
typedef __list_iterator<T> self;
node* node_; // 成员变量,为一个节点的指针
__list_iterator(node* node)
: node_(node) { }
// 解引用操作符重载
T& operator*() {
return node_->data_;
}
// 后置++操作符重载,完成迭代器的移动
self& operator++() {
node_ = node_->next_; // 移动到下一个节点
return *this;
}
// !=操作符重载
bool operator!=(const self& other) {
return node_ != other.node_;
}
};
2.2 引入const迭代器
如上述代码,若实现const
迭代器,本能的反映是再封装一个迭代器类,但这个类与普通迭代器实现是没有区别的,只是在返回参数上有所改变。而再封装一个类导致了代码的冗余,我们是否可以只封装一个迭代器类,实现const
和非const
功能呢?
2.2.1 参考STL源代码
template<class T, class Ref, class Ptr>
struct __list_iterator {
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
typedef __list_iterator<T, Ref, Ptr> self;
}
- 从STL源代码中我们可以看到,
list
迭代器在设计中,使用了三个模板参数,分别是:- 数据类型
T
- 引用数据类型
Ref
- 指针数据类型
Ptr
- 数据类型
2.2.2 完善迭代器
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* node)
: node_(node) { }
// 解引用操作符重载
Ref operator*() {
return node_->data_;
}
// 后置++操作符重载,完成迭代器的移动
self& operator++() {
node_ = node_->next_; // 移动到下一个节点
return *this;
}
// !=操作符重载
bool operator!=(const self& other) {
return node_ != other.node_;
}
// ->操作符重载
Ptr operator->() {
return &(node_->data_);
}
};
// typedef迭代器类
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
3、迭代器实现机制
操作类型 | 失效情况 |
---|---|
插入操作 | 不影响现有迭代器 |
删除操作 | 被删除元素的迭代器立即失效 |
合并/转移操作 | 被转移元素的迭代器失效 |
结语
list
迭代器设计体现了C++模板元编程的强大能力,通过精巧的类型系统设计和操作符重载,使得链表容器能够无缝接入STL算法体系。理解其实现原理不仅有助于深入掌握STL工作机制,更能提升我们对迭代器设计模式的认识。