【C++指南】C++ list容器完全解读(三):list迭代器的实现与优化
.
💓 博客主页:倔强的石头的CSDN主页
📝Gitee主页:倔强的石头的gitee主页
⏩ 文章专栏:《C++指南》
期待您的关注![]()
文章目录
- 引言
- 一、普通迭代器:链表的“导航指针”
- 1.1 迭代器的本质
- 1.2 迭代器与链表的关系
- 二、const迭代器:数据保护的实现
- 2.1 为什么需要const迭代器?
- 2.2 独立const迭代器的实现
- 三、模板复用:合并普通与const迭代器
- 3.1 STL的迭代器优化思想
- 3.2 统一迭代器模板实现
- 3.3 在list类中实例化迭代器
- 四、总结与系列回顾
引言
在上一篇文章【C++指南】C++ list容器完全解读(二):list模拟实现,底层架构揭秘中,我们实现了list的核心架构。
本文作为系列第三篇,将深入剖析迭代器的底层实现,揭示STL如何通过迭代器实现“透明访问”与类型安全。通过本文,您将掌握:
- 迭代器与链表的协作原理
- const迭代器的设计思想
- 模板参数复用实现迭代器统一
一、普通迭代器:链表的“导航指针”
1.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; } // 成员访问运算符 T* operator->() { return &(_node->data); } // 前置++ self& operator++() { _node = _node->next; return *this; } // 后置++ self operator++(int) { self tmp = *this; _node = _node->next; return tmp; } // 比较运算符 bool operator==(const self& it) { return _node == it._node; }
};
关键设计:
- 通过
_node
指针直接操作链表节点 - 运算符重载支持
++
、*
、->
等语法,模拟指针行为
1.2 迭代器与链表的关系
list
类通过begin()
和end()
返回迭代器begin()
指向头节点的下一个节点,也就是第一个有效节点(如果链表为空,则指向头节点)end()
指向头节点(哨兵节点),标识遍历终点
// list类中的迭代器定义
typedef list_iterator<T> iterator;
iterator begin() { return _head->next; }
iterator end() { return _head; }
二、const迭代器:数据保护的实现
2.1 为什么需要const迭代器?
若直接对普通迭代器添加const
修饰:
const iterator it = lst.begin();
这仅表示it
本身不可修改(不能移动迭代器),但仍可修改其指向的数据:
*it = 100; // 合法操作!
真正的const迭代器应禁止修改数据内容,需返回const T&
。
2.2 独立const迭代器的实现
template<class T>
struct list_const_iterator { typedef list_node<T> Node; typedef list_const_iterator<T> self; const Node* _node; // 关键:节点指针为const list_const_iterator(Node* node) : _node(node) {} // 返回const引用,禁止修改数据 const T& operator*() { return _node->data; } // 其余运算符重载与普通迭代器一致
};
在list类中定义:
typedef list_const_iterator<T> const_iterator;
const_iterator begin() const { return _head->next; }
const_iterator end() const { return _head; }
三、模板复用:合并普通与const迭代器
3.1 STL的迭代器优化思想
STL通过模板参数传递返回类型,复用同一份代码生成普通和const迭代器,避免冗余。
3.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; } Ptr operator->() { return &(_node->data); } // 运算符重载逻辑不变 self& operator++() { _node = _node->next; return *this; } // ... 其他运算符
};
3.3 在list类中实例化迭代器
// 普通迭代器
typedef list_iterator<T, T&, T*> iterator;
// const迭代器
typedef list_iterator<T, const T&, const T*> const_iterator;
原理:
Ref
控制operator*
的返回类型(T&
或const T&
)Ptr
控制operator->
的返回类型(T*
或const T*
)
四、总结与系列回顾
本文从迭代器的基本实现出发,逐步解析了const迭代器的必要性及模板复用技术。通过统一模板设计,我们实现了代码的高度复用,同时保证了类型安全。
系列文章总结:
- 【C++指南】STL list容器完全解读(一):从入门到掌握基础操作:剖析接口与使用场景
- 【C++指南】C++ list容器完全解读(二):list模拟实现,底层架构揭秘:揭秘双向链表与深拷贝逻辑
- 【C++指南】C++ list容器完全解读(三):list迭代器的实现与优化:深入迭代器封装与优化