设计模式(C++)详解——迭代器模式(1)
<摘要>
迭代器模式是软件设计模式中的一颗"璀璨明珠",它巧妙地将集合的遍历操作与集合本身分离开来,让开发者能够以统一的方式访问各种不同的数据结构。本文将带领读者穿越迭代器模式的发展历程,深入剖析其设计哲学,并通过丰富的C++实战案例展示其强大威力。从STL的经典实现到现代C++的迭代器进阶技巧,我们将全方位解密这个让代码变得优雅而强大的设计模式。
<解析>
迭代器模式:遍历艺术的深度解析
1. 背景与核心概念:从"手工遍历"到"自动化导航"的进化史
1.1 历史演进:迭代器模式的"前世今生"
石器时代:手工遍历的困境
在迭代器模式出现之前,程序员们不得不面对各种数据结构的"个性差异":
// 数组遍历 - 简单但脆弱
int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {// 硬编码大小,容易越界
}// 链表遍历 - 每種数据结构都有自己的一套
struct Node {int data;Node* next;
};Node* current = head;
while (current != nullptr) {// 处理current->datacurrent = current->next; // 必须了解链表内部结构
}
工业革命:迭代器模式的诞生
1980年代,随着面向对象编程的兴起,设计模式理论开始系统化。迭代器模式在1994年被GoF(Gang of Four)正式收录,成为23种经典设计模式之一。
现代文明:C++ STL的辉煌
C++标准模板库(STL)将迭代器模式发挥到极致,创造了"泛型编程"的奇迹:
#include <vector>
#include <list>
#include <set>// 统一的遍历方式,无论底层数据结构如何
std::vector<int> vec = {1, 2, 3};
std::list<int> lst = {4, 5, 6};
std::set<int> st = {7, 8, 9};// 同样的代码,不同的容器!
for (auto it = vec.begin(); it != vec.end(); ++it) { /* ... */ }
for (auto it = lst.begin(); it != lst.end(); ++it) { /* ... */ }
for (auto it = st.begin(); it != st.end(); ++it) { /* ... */ }
1.2 核心概念解析:迭代器模式的"五脏六腑"
UML类图揭示的设计奥秘
核心角色深度解析
角色 | 职责 | 现实比喻 | C++对应 |
---|---|---|---|
Iterator(迭代器) | 定义访问和遍历元素的接口 | 博物馆的导览器 | std::iterator |
ConcreteIterator(具体迭代器) | 实现迭代器接口,记录当前遍历位置 | 具体的导览路线 | std::vector<int>::iterator |
Aggregate(聚合) | 定义创建迭代器对象的接口 | 博物馆本身 | 各种STL容器 |
ConcreteAggregate(具体聚合) | 实现创建迭代器的接口,返回具体迭代器实例 | 具体的博物馆 | std::vector<int> |
迭代器分类体系(C++标准)
2. 设计意图与考量:优雅遍历的哲学思考
2.1 核心设计目标:分离的智慧
迭代器模式的核心理念可以用一句话概括:“不要让集合的客户关心它如何存储元素,只关心如何访问元素”。
设计目标矩阵
设计目标 | 实现方式 | 受益方 |
---|---|---|
封装性 | 将遍历逻辑从集合中分离 | 集合类可以独立演化 |
统一接口 | 为不同集合提供相同的遍历方式 | 客户端代码更简洁 |
支持多种遍历 | 可为同一集合提供不同迭代器 | 灵活性大大增强 |
简化集合接口 | 集合只需提供创建迭代器的方法 | 集合类更专注数据存储 |
2.2 设计权衡:完美背后的妥协
优点深度剖析
- 单一职责原则:集合管理数据,迭代器处理遍历
- 开闭原则:可以轻松添加新的迭代器而不修改集合
- 并行遍历:多个迭代器可以同时遍历同一集合
- 延迟遍历:可以在需要时才获取元素(特别适合大数据集)
缺点与挑战
- 复杂性增加:简单集合使用迭代器可能显得"杀鸡用牛刀"
- 性能开销:对于小型集合,直接访问可能更快
- C++特定问题:
const_iterator
与iterator
的区分
2.3 C++迭代器的特殊考量
const正确性难题
std::vector<int> vec = {1, 2, 3};
const std::vector<int> cvec = {4, 5, 6};// 正确:普通迭代器可修改元素
auto it = vec.begin();
*it = 10; // OK// 正确:const迭代器防止修改
auto cit = cvec.begin();
// *cit = 10; // 编译错误!// 但容易出错的情况:
void print_vector(const std::vector<int>& vec) {// 错误:begin()返回const_iterator,但用auto接收可能出错for (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";}
}
迭代器失效问题
std::vector<int> vec = {1, 2, 3, 4, 5};
auto it = vec.begin() + 2; // 指向3vec.push_back(6); // 可能引起重新分配内存
// it可能失效!不能再使用
3. 实例与应用场景:从理论到实践的华丽转身
3.1 案例一:自定义集合类的迭代器实现
场景描述:实现一个支持多种遍历方式的二叉树集合
/*** @brief 二叉树节点模板类* * 支持任意可比较类型,提供基本的二叉树节点功能。* 包含左子节点、右子节点和父节点指针,以及数据存储。* * @tparam T 节点数据类型,必须支持比较操作*/
template<typename T>
class BinaryTreeNode {
public:T data;std::unique_ptr<BinaryTreeNode> left;std::unique_ptr<BinaryTreeNode> right;BinaryTreeNode* parent; // 用于反向遍历BinaryTreeNode(const T& value, BinaryTreeNode* parent_node = nullptr): data(value), parent(parent_node) {}
};/*** @brief 二叉树集合模板类* * 实现基本的二叉搜索树功能,支持插入、查找、删除操作。* 提供多种迭代器:前序、中序、后序、层序遍历。* 线程不安全,多线程环境需要外部同步。* * @tparam T 元素类型,必须支持比较操作*/
template<typename T>
class BinaryTree {
private:std::unique_ptr<BinaryTreeNode<T>> root;size_t size_ = 0;// 递归插入辅助函数BinaryTreeNode<T>* insert_recursive(std::unique_ptr<BinaryTreeNode<T>>& node, const T& value, BinaryTreeNode<T>* parent) {if (!node) {node = std::make_unique<BinaryTreeNode<T>>(value, parent);size_++;return node.get();}if (value < node->data) {return insert_recursive(node->left, value, node.get());} else if (value > node->data) {return insert_recursive(node->right, value, node.get());}return node.get(); // 值已存在}public:BinaryTree() = default;/*** @brief 向树中插入新元素* @param value 要插入的值* @return 插入的节点指针,如果值已存在则返回现有节点*/BinaryTreeNode<T>* insert(const T& value) {return insert_recursive(root, value, nullptr);}size_t size() const { return size_; }bool empty() const { return size_ == 0; }/*** @brief 中序迭代器类* * 实现二叉树的中序遍历(左-根-右),* 符合二叉搜索树的排序顺序。*/class InorderIterator {private:BinaryTreeNode<T>* current;/*** @brief 查找中序遍历的下一个节点* @return 下一个节点指针,如果没有则返回nullptr*/BinaryTreeNode<T>* find_next() {if (!current) return nullptr;// 如果有右子树,下一个节点是右子树的最左节点if (current->right) {BinaryTreeNode<T>* temp = current->right.get();while (temp->left) {temp = temp->left.get();}return temp;}// 否则,向上查找直到当前节点是父节点的左子节点BinaryTreeNode<T>* temp = current;BinaryTreeNode<T>* parent = temp->parent;while (parent && temp == parent->right.get()) {temp = parent;parent = parent->parent;}return parent;}public:using iterator_category = std::forward_iterator_tag;using value_type = T;using difference_type = std::ptrdiff_t;using pointer = T*;using reference = T&;explicit InorderIterator(BinaryTreeNode<T>* node = nullptr) : current(node) {}/*** @brief 解引用操作符* @return 当前节点的数据引用* @throws std::runtime_error 如果迭代器无效*/T& operator*() {if (!current) throw std::runtime_error("Dereferencing invalid iterator");return current->data;}T* operator->() { return ¤t->data; }/*** @brief 前缀递增操作符* @return 递增后的迭代器引用*/InorderIterator& operator++() {current = find_next();return *this;}InorderIterator operator++(int) {InorderIterator temp = *this;++(*this);return temp;}bool operator==(const InorderIterator& other) const {return current == other.current;}bool operator!=(const InorderIterator& other) const {return !(*this == other);}};/*** @brief 获取中序遍历起始迭代器* @return 指向最小元素的迭代器*/InorderIterator begin() {if (!root) return InorderIterator(nullptr);BinaryTreeNode<T>* temp = root.get();while (temp->left) {temp = temp->left.get();}return InorderIterator(temp);}/*** @brief 获取中序遍历结束迭代器* @return 结束迭代器(nullptr)*/InorderIterator end() {return InorderIterator(nullptr);}/*** @brief 常量中序迭代器类* * 提供对常量二叉树的只读遍历能力,* 防止通过迭代器修改树中的数据。*/class ConstInorderIterator {private:const BinaryTreeNode<T>* current;const BinaryTreeNode<T>* find_next() {if (!current) return nullptr;if (current->right) {const BinaryTreeNode<T>* temp = current->right.get();while (temp->left) {temp = temp->left.get();}return temp;}const BinaryTreeNode<T>* temp = current;const BinaryTreeNode<T>* parent = temp->parent;while (parent && temp == parent->right.get()) {temp = parent;parent = parent->parent;}return parent;}public:using iterator_category = std::forward_iterator_tag;using value_type = const T;using difference_type = std::ptrdiff_t;using pointer = const T*;using reference = const T&;explicit ConstInorderIterator(const BinaryTreeNode<T>* node = nullptr) : current(node) {}const T& operator*() const {if (!current) throw std::runtime_error("Dereferencing invalid iterator");return current->data;}const T* operator->() const { return ¤t->data; }ConstInorderIterator& operator++() {current = find_next();return *this;}ConstInorderIterator operator++(int) {ConstInorderIterator temp = *this;++(*this);return temp;}bool operator==(const ConstInorderIterator& other) const {return current == other.current;}bool operator!=(const ConstInorderIterator& other) const {return !(*this == other);}};ConstInorderIterator begin() const {if (!root) return ConstInorderIterator(nullptr);const BinaryTreeNode<T>* temp = root.get();while (temp->left) {temp = temp->left.get();}return ConstInorderIterator(temp);}ConstInorderIterator end() const {return ConstInorderIterator(nullptr);}
};// 使用示例
void binary_tree_demo() {BinaryTree<int> tree;// 插入测试数据tree.insert(50);tree.insert(30);tree.insert(70);tree.insert(20);tree.insert(40);tree.insert(60);tree.insert(80);std::cout << "中序遍历结果: ";for (auto it = tree.begin(); it != tree.end(); ++it) {std::cout << *it << " "; // 输出: 20 30 40 50 60 70 80}std::cout << std::endl;// 使用C++11范围for循环(需要begin/end方法)std::cout << "范围for循环: ";for (const auto& value : tree) {std::cout << value << " ";}std::cout << std::endl;
}
3.2 案例二:支持多种遍历策略的图结构
场景描述:实现一个图数据结构,支持深度优先搜索(DFS)和广度优先搜索(BFS)迭代器
#include <queue>
#include <stack>
#include <unordered_set>/*** @brief 图节点模板类* * 表示图中的顶点,包含数据和邻接表。* 支持有向图和无向图,通过边的添加方式决定。* * @tparam T 节点数据类型*/
template<typename T>
class GraphNode {
public:T data;std::vector<std::shared_ptr<GraphNode<T>>> neighbors;GraphNode(const T& value) : data(value) {}/*** @brief 添加邻接节点* @param neighbor 邻接节点指针* @param bidirectional 是否双向连接(无向图)*/void add_neighbor(std::shared_ptr<GraphNode<T>> neighbor, bool bidirectional = false) {neighbors.push_back(neighbor);if (bidirectional) {neighbor->neighbors.push_back(shared_from_this());}}
};/*** @brief 图数据结构模板类* * 实现基本的图操作,支持多种遍历策略。* 使用智能指针管理内存,避免内存泄漏。* 提供DFS和BFS迭代器实现。* * @tparam T 节点数据类型*/
template<typename T>
class Graph {
private:std::vector<std::shared_ptr<GraphNode<T>>> nodes;public:/*** @brief 添加新节点到图中* @param value 节点数据* @return 新节点的共享指针*/std::shared_ptr<GraphNode<T>> add_node(const T& value) {auto node = std::make_shared<GraphNode<T>>(value);nodes.push_back(node);return node;}/*** @brief 深度优先搜索迭代器* * 使用栈实现DFS遍历,提供图的深度优先访问顺序。* 非递归实现,避免栈溢出问题。*/class DFSIterator {private:std::stack<std::shared_ptr<GraphNode<T>>> stack;std::unordered_set<std::shared_ptr<GraphNode<T>>> visited;/*** @brief 将节点的未访问邻居压入栈中* @param node 当前节点*/void push_unvisited_neighbors(std::shared_ptr<GraphNode<T>> node) {for (auto& neighbor : node->neighbors) {if (visited.find(neighbor) == visited.end()) {stack.push(neighbor);}}}public:using iterator_category = std::input_iterator_tag;using value_type = T;using difference_type = std::ptrdiff_t;using pointer = T*;using reference = T&;/*** @brief 从指定起始节点构造DFS迭代器* @param start_node 起始节点指针*/DFSIterator(std::shared_ptr<GraphNode<T>> start_node = nullptr) {if (start_node) {stack.push(start_node);++(*this); // 移动到第一个元素}}T& operator*() {if (stack.empty()) throw std::runtime_error("Dereferencing invalid iterator");return stack.top()->data;}T* operator->() { return &stack.top()->data; }/*** @brief 前缀递增操作符* @return 递增后的迭代器引用*/DFSIterator& operator++() {if (stack.empty()) return *this;auto current = stack.top();stack.pop();visited.insert(current);push_unvisited_neighbors(current);// 跳过已访问的栈顶元素,直到找到未访问的或栈空while (!stack.empty() && visited.find(stack.top()) != visited.end()) {stack.pop();}return *this;}DFSIterator operator++(int) {DFSIterator temp = *this;++(*this);return temp;}bool operator==(const DFSIterator& other) const {return stack.empty() && other.stack.empty();}bool operator!=(const DFSIterator& other) const {return !(*this == other);}};/*** @brief 广度优先搜索迭代器* * 使用队列实现BFS遍历,提供图的广度优先访问顺序。* 按层次遍历图节点。*/class BFSIterator {private:std::queue<std::shared_ptr<GraphNode<T>>> queue;std::unordered_set<std::shared_ptr<GraphNode<T>>> visited;/*** @brief 将节点的未访问邻居加入队列* @param node 当前节点*/void enqueue_unvisited_neighbors(std::shared_ptr<GraphNode<T>> node) {for (auto& neighbor : node->neighbors) {if (visited.find(neighbor) == visited.end()) {queue.push(neighbor);}}}public:using iterator_category = std::input_iterator_tag;using value_type = T;using difference_type = std::ptrdiff_t;using pointer = T*;using reference = T&;BFSIterator(std::shared_ptr<GraphNode<T>> start_node = nullptr) {if (start_node) {queue.push(start_node);visited.insert(start_node);}}T& operator*() {if (queue.empty()) throw std::runtime_error("Dereferencing invalid iterator");return queue.front()->data;}T* operator->() { return &queue.front()->data; }BFSIterator& operator++() {if (queue.empty()) return *this;auto current = queue.front();queue.pop();enqueue_unvisited_neighbors(current);return *this;}BFSIterator operator++(int) {BFSIterator temp = *this;++(*this);return temp;}bool operator==(const BFSIterator& other) const {return queue.empty() && other.queue.empty();}bool operator!=(const BFSIterator& other) const {return !(*this == other);}};/*** @brief 获取从指定节点开始的DFS迭代器* @param start_node 起始节点* @return DFS迭代器*/DFSIterator dfs_begin(std::shared_ptr<GraphNode<T>> start_node) {return DFSIterator(start_node);}DFSIterator dfs_end() {return DFSIterator();}/*** @brief 获取从指定节点开始的BFS迭代器* @param start_node 起始节点* @return BFS迭代器*/BFSIterator bfs_begin(std::shared_ptr<GraphNode<T>> start_node) {return BFSIterator(start_node);}BFSIterator bfs_end() {return BFSIterator();}
};// 使用示例
void graph_traversal_demo() {Graph<std::string> social_network;// 创建社交网络节点auto alice = social_network.add_node("Alice");auto bob = social_network.add_node("Bob");auto charlie = social_network.add_node("Charlie");auto diana = social_network.add_node("Diana");auto eve = social_network.add_node("Eve");// 建立朋友关系(无向图)alice->add_neighbor(bob, true);alice->add_neighbor(charlie, true);bob->add_neighbor(diana, true);charlie->add_neighbor(eve, true);diana->add_neighbor(eve, true);std::cout << "从Alice开始的DFS遍历: ";for (auto it = social_network.dfs_begin(alice); it != social_network.dfs_end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;std::cout << "从Alice开始的BFS遍历: ";for (auto it = social_network.bfs_begin(alice); it != social_network.bfs_end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;
}
3.3 案例三:STL兼容的自定义迭代器
场景描述:实现一个完全兼容STL算法的自定义迭代器
#include <algorithm>
#include <numeric>
#include <memory>/*** @brief 固定大小数组的STL兼容迭代器* * 演示如何实现符合STL标准的随机访问迭代器,* 可以与所有STL算法无缝协作。* * @tparam T 数组元素类型* @tparam N 数组大小*/
template<typename T, size_t N>
class FixedArray {
private:T data[N];public:/*** @brief 随机访问迭代器类* * 实现所有随机访问迭代器要求的操作,* 包括算术运算、比较运算和下标访问。*/class Iterator {private:T* ptr;public:// STL迭代器类型定义(必须)using iterator_category = std::random_access_iterator_tag;using value_type = T;using difference_type = std::ptrdiff_t;using pointer = T*;using reference = T&;explicit Iterator(T* p = nullptr) : ptr(p) {}// 解引用操作reference operator*() const { return *ptr; }pointer operator->() const { return ptr; }reference operator[](difference_type n) const { return ptr[n]; }// 递增递减操作Iterator& operator++() { ++ptr; return *this; }Iterator operator++(int) { Iterator temp = *this; ++ptr; return temp; }Iterator& operator--() { --ptr; return *this; }Iterator operator--(int) { Iterator temp = *this; --ptr; return temp; }// 算术运算Iterator& operator+=(difference_type n) { ptr += n; return *this; }Iterator& operator-=(difference_type n) { ptr -= n; return *this; }Iterator operator+(difference_type n) const { return Iterator(ptr + n); }Iterator operator-(difference_type n) const { return Iterator(ptr - n); }difference_type operator-(const Iterator& other) const { return ptr - other.ptr; }// 比较运算bool operator==(const Iterator& other) const { return ptr == other.ptr; }bool operator!=(const Iterator& other) const { return ptr != other.ptr; }bool operator<(const Iterator& other) const { return ptr < other.ptr; }bool operator>(const Iterator& other) const { return ptr > other.ptr; }bool operator<=(const Iterator& other) const { return ptr <= other.ptr; }bool operator>=(const Iterator& other) const { return ptr >= other.ptr; }// 友元函数friend Iterator operator+(difference_type n, const Iterator& it) {return Iterator(it.ptr + n);}};/*** @brief 常量随机访问迭代器类* * 提供只读访问能力,防止通过迭代器修改数据。*/class ConstIterator {private:const T* ptr;public:using iterator_category = std::random_access_iterator_tag;using value_type = const T;using difference_type = std::ptrdiff_t;using pointer = const T*;using reference = const T&;explicit ConstIterator(const T* p = nullptr) : ptr(p) {}// 从普通迭代器构造常量迭代器ConstIterator(const Iterator& other) : ptr(other.operator->()) {}reference operator*() const { return *ptr; }pointer operator->() const { return ptr; }reference operator[](difference_type n) const { return ptr[n]; }ConstIterator& operator++() { ++ptr; return *this; }ConstIterator operator++(int) { ConstIterator temp = *this; ++ptr; return temp; }ConstIterator& operator--() { --ptr; return *this; }ConstIterator operator--(int) { ConstIterator temp = *this; --ptr; return temp; }ConstIterator& operator+=(difference_type n) { ptr += n; return *this; }ConstIterator& operator-=(difference_type n) { ptr -= n; return *this; }ConstIterator operator+(difference_type n) const { return ConstIterator(ptr + n); }ConstIterator operator-(difference_type n) const { return ConstIterator(ptr - n); }difference_type operator-(const ConstIterator& other) const { return ptr - other.ptr; }bool operator==(const ConstIterator& other) const { return ptr == other.ptr; }bool operator!=(const ConstIterator& other) const { return ptr != other.ptr; }bool operator<(const ConstIterator& other) const { return ptr < other.ptr; }bool operator>(const ConstIterator& other) const { return ptr > other.ptr; }bool operator<=(const ConstIterator& other) const { return ptr <= other.ptr; }bool operator>=(const ConstIterator& other) const { return ptr >= other.ptr; }friend ConstIterator operator+(difference_type n, const ConstIterator& it) {return ConstIterator(it.ptr + n);}};// 容器接口方法Iterator begin() { return Iterator(data); }Iterator end() { return Iterator(data + N); }ConstIterator begin() const { return ConstIterator(data); }ConstIterator end() const { return ConstIterator(data + N); }ConstIterator cbegin() const { return ConstIterator(data); }ConstIterator cend() const { return ConstIterator(data + N); }// 元素访问T& operator[](size_t index) { return data[index]; }const T& operator[](size_t index) const { return data[index]; }size_t size() const { return N; }// 数据访问T* get_data() { return data; }const T* get_data() const { return data; }
};// 使用示例:展示与STL算法的完美兼容性
void stl_compatibility_demo() {FixedArray<int, 5> arr = {1, 2, 3, 4, 5};// 使用STL算法排序(需要随机访问迭代器)std::sort(arr.begin(), arr.end());// 使用STL算法查找auto it = std::find(arr.begin(), arr.end(), 3);if (it != arr.end()) {std::cout << "找到元素: " << *it << std::endl;}// 使用STL算法累加int sum = std::accumulate(arr.begin(), arr.end(), 0);std::cout << "元素总和: " << sum << std::endl;// 使用STL算法变换std::transform(arr.begin(), arr.end(), arr.begin(), [](int x) { return x * 2; });// 输出结果std::cout << "处理后的数组: ";std::copy(arr.begin(), arr.end(), std::ostream_iterator<int>(std::cout, " "));std::cout << std::endl;// 测试常量迭代器const FixedArray<int, 5>& carr = arr;std::cout << "常量迭代器遍历: ";for (auto it = carr.begin(); it != carr.end(); ++it) {std::cout << *it << " ";// *it = 10; // 编译错误!常量迭代器禁止修改}std::cout << std::endl;
}
4. 现代C++迭代器进阶技巧
4.1 迭代器适配器:强大的功能组合
反向迭代器实现
template<typename Iterator>
class ReverseIterator {
private:Iterator current;public:using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;using value_type = typename std::iterator_traits<Iterator>::value_type;using difference_type = typename std::iterator_traits<Iterator>::difference_type;using pointer = typename std::iterator_traits<Iterator>::pointer;using reference = typename std::iterator_traits<Iterator>::reference;explicit ReverseIterator(Iterator it) : current(it) {}reference operator*() const {Iterator temp = current;return *--temp;}pointer operator->() const {Iterator temp = current;--temp;return temp.operator->();}ReverseIterator& operator++() {--current;return *this;}ReverseIterator operator++(int) {ReverseIterator temp = *this;--current;return temp;}bool operator==(const ReverseIterator& other) const {return current == other.current;}bool operator!=(const ReverseIterator& other) const {return !(*this == other);}
};
4.2 基于范围的for循环支持
C++11范围for循环的原理
// 编译器将范围for循环展开为:
// {
// auto&& __range = range_expression;
// auto __begin = begin_expr;
// auto __end = end_expr;
// for (; __begin != __end; ++__begin) {
// range_declaration = *__begin;
// loop_statement;
// }
// }// 因此,要支持范围for循环,只需要实现begin()和end()方法
class MyContainer {
public:// 必须提供begin和end方法Iterator begin() { /* ... */ }Iterator end() { /* ... */ }ConstIterator begin() const { /* ... */ }ConstIterator end() const { /* ... */ }
};
5. 编译测试与性能分析
5.1 完整的测试程序
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
#include <memory>
#include <stack>
#include <queue>
#include <unordered_set>// 插入上面所有的实现代码.../*** @brief 迭代器性能测试函数* * 对比不同迭代器的性能表现,包括原始指针、STL迭代器和自定义迭代器。*/
void iterator_performance_test() {const size_t SIZE = 1000000;std::vector<int> vec(SIZE);std::iota(vec.begin(), vec.end(), 0); // 填充0到SIZE-1// 测试1:原始指针遍历auto start1 = std::chrono::high_resolution_clock::now();int sum1 = 0;for (size_t i = 0; i < SIZE; ++i) {sum1 += vec[i];}auto end1 = std::chrono::high_resolution_clock::now();// 测试2:STL迭代器遍历auto start2 = std::chrono::high_resolution_clock::now();int sum2 = 0;for (auto it = vec.begin(); it != vec.end(); ++it) {sum2 += *it;}auto end2 = std::chrono::high_resolution_clock::now();// 测试3:范围for循环auto start3 = std::chrono::high_resolution_clock::now();int sum3 = 0;for (int value : vec) {sum3 += value;}auto end3 = std::chrono::high_resolution_clock::now();// 计算耗时auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1);auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(end2 - start2);auto duration3 = std::chrono::duration_cast<std::chrono::microseconds>(end3 - start3);std::cout << "=== 迭代器性能测试结果 ===\n";std::cout << "数据量: " << SIZE << " 个元素\n";std::cout << "原始指针遍历: " << duration1.count() << " μs\n";std::cout << "STL迭代器遍历: " << duration2.count() << " μs\n";std::cout << "范围for循环: " << duration3.count() << " μs\n";std::cout << "总和验证: " << sum1 << " = " << sum2 << " = " << sum3 << "\n\n";
}int main() {std::cout << "=== 迭代器模式深度解析测试程序 ===\n\n";// 基本功能演示std::cout << "1. 二叉树迭代器演示:\n";binary_tree_demo();std::cout << "\n";std::cout << "2. 图遍历迭代器演示:\n";graph_traversal_demo();std::cout << "\n";std::cout << "3. STL兼容迭代器演示:\n";stl_compatibility_demo();std::cout << "\n";std::cout << "4. 迭代器性能测试:\n";iterator_performance_test();// 高级特性演示std::cout << "5. 现代C++迭代器特性演示:\n";// 演示迭代器分类的重要性std::vector<int> vec = {3, 1, 4, 1, 5, 9, 2, 6};std::list<int> lst = {3, 1, 4, 1, 5, 9, 2, 6};// vector支持随机访问,可以排序std::sort(vec.begin(), vec.end());std::cout << "排序后的vector: ";for (int v : vec) std::cout << v << " ";std::cout << std::endl;// list不支持随机访问,需要使用成员函数排序// std::sort(lst.begin(), lst.end()); // 编译错误!lst.sort(); // 必须使用list的成员函数std::cout << "排序后的list: ";for (int v : lst) std::cout << v << " ";std::cout << std::endl;return 0;
}
5.2 Makefile配置
# Makefile for Iterator Pattern Deep Analysis
CXX = g++
CXXFLAGS = -std=c++17 -Wall -Wextra -O3 -march=native
TARGET = iterator_analysis
SOURCES = main.cpp# 调试版本配置
DEBUG_CXXFLAGS = -std=c++17 -Wall -Wextra -g -O0 -DDEBUG# 性能分析配置
PROFILE_CXXFLAGS = -std=c++17 -Wall -Wextra -O3 -pg$(TARGET): $(SOURCES)$(CXX) $(CXXFLAGS) -o $(TARGET) $(SOURCES)debug:$(CXX) $(DEBUG_CXXFLAGS) -o $(TARGET)_debug $(SOURCES)profile:$(CXX) $(PROFILE_CXXFLAGS) -o $(TARGET)_profile $(SOURCES)sanitize:$(CXX) $(DEBUG_CXXFLAGS) -fsanitize=address -fsanitize=undefined -o $(TARGET)_sanitize $(SOURCES)run: $(TARGET)./$(TARGET)clean:rm -f $(TARGET) $(TARGET)_debug $(TARGET)_profile $(TARGET)_sanitize gmon.out.PHONY: all debug profile sanitize run clean
编译和运行:
# 普通编译
make# 调试版本
make debug# 运行测试
./iterator_analysis
6. 总结:迭代器模式的智慧结晶
迭代器模式不仅仅是23种设计模式之一,更是C++标准库的基石。通过深入理解迭代器模式,我们可以:
6.1 核心价值总结
- 抽象威力:将遍历算法与数据结构解耦
- 统一接口:为不同集合提供相同的访问方式
- 算法复用:STL算法可以应用于任何提供迭代器的容器
- 类型安全:编译时检查确保迭代器正确使用
6.2 现代C++最佳实践
实践要点 | 说明 | 示例 |
---|---|---|
遵循STL约定 | 实现标准迭代器类型定义 | iterator_category , value_type 等 |
保证const正确性 | 提供const_iterator版本 | begin() const 返回const_iterator |
支持范围for循环 | 实现begin()和end()方法 | 自动支持C++11范围for |
注意迭代器失效 | 文档说明迭代器何时失效 | 修改容器时迭代器可能失效 |
提供迭代器特征 | 使用std::iterator_traits | 使算法能识别迭代器能力 |
6.3 未来发展趋势
随着C++标准的演进,迭代器模式也在不断发展:
- C++20范围库:提供更声明式的迭代方式
- 概念(Concepts):对迭代器要求的编译时检查
- 协程(Coroutines):可能产生新的迭代模式
- 并行算法:迭代器需要支持并行遍历
迭代器模式的成功告诉我们:优秀的抽象能够跨越时间和技术的变迁,成为编程语言永恒的基石。掌握迭代器模式,不仅是学习一种设计模式,更是理解现代软件设计哲学的关键一步。