迭代器模式与几个经典的C++实现

迭代器模式详解

1. 定义与意图

迭代器模式(Iterator Pattern) 是一种行为设计模式,它提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

主要意图:

  • 为不同的聚合结构提供统一的遍历接口。

  • 将遍历数据的职责与聚合对象本身分离,简化聚合接口。

  • 支持以不同方式遍历同一个聚合(如前序、中序、后序遍历二叉树)。

2. 模式结构

迭代器模式包含以下几个角色:

  1. Iterator(迭代器接口):定义访问和遍历元素的接口。

  2. ConcreteIterator(具体迭代器):实现迭代器接口,跟踪遍历的当前位置。

  3. Aggregate(聚合接口):定义创建相应迭代器对象的接口。

  4. ConcreteAggregate(具体聚合):实现创建相应迭代器的接口,返回具体迭代器的实例。

3. 适用场景

  • 需要访问聚合对象的内容而不暴露其内部表示

  • 支持对聚合对象的多种遍历方式

  • 为遍历不同的聚合结构提供统一的接口

4. 优点

  • 单一职责原则:将遍历算法与聚合对象分离

  • 开闭原则:可以引入新的迭代器而不修改现有代码

  • 可以并行遍历同一聚合,因为每个迭代器都有自己的状态

  • 可以暂停遍历并在需要时继续

5. 缺点

  • 对于简单的集合可能过于复杂

  • 某些情况下,使用专门的遍历方法可能比迭代器更高效

C++ 实现例子

例子1:自定义数组容器的迭代器

#include <iostream>
#include <stdexcept>template <typename T, size_t SIZE>
class Array {
private:T data[SIZE];public:// 迭代器类class Iterator {private:T* ptr;public:explicit Iterator(T* p) : ptr(p) {}// 前置++Iterator& operator++() {++ptr;return *this;}// 后置++Iterator operator++(int) {Iterator temp = *this;++ptr;return temp;}T& operator*() const {return *ptr;}T* operator->() const {return ptr;}bool operator==(const Iterator& other) const {return ptr == other.ptr;}bool operator!=(const Iterator& other) const {return !(*this == other);}};// const迭代器类class ConstIterator {private:const T* ptr;public:explicit ConstIterator(const T* p) : ptr(p) {}ConstIterator& operator++() {++ptr;return *this;}ConstIterator operator++(int) {ConstIterator temp = *this;++ptr;return temp;}const T& operator*() const {return *ptr;}const T* operator->() const {return ptr;}bool operator==(const ConstIterator& other) const {return ptr == other.ptr;}bool operator!=(const ConstIterator& other) const {return !(*this == other);}};// 获取开始迭代器Iterator begin() {return Iterator(data);}Iterator end() {return Iterator(data + SIZE);}ConstIterator begin() const {return ConstIterator(data);}ConstIterator end() const {return ConstIterator(data + SIZE);}ConstIterator cbegin() const {return ConstIterator(data);}ConstIterator cend() const {return ConstIterator(data + SIZE);}T& operator[](size_t index) {if (index >= SIZE) {throw std::out_of_range("Index out of range");}return data[index];}const T& operator[](size_t index) const {if (index >= SIZE) {throw std::out_of_range("Index out of range");}return data[index];}size_t size() const {return SIZE;}
};// 使用示例
int main() {Array<int, 5> arr = {1, 2, 3, 4, 5};// 使用迭代器遍历std::cout << "Using iterator: ";for (auto it = arr.begin(); it != arr.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;// 使用范围for循环(基于迭代器)std::cout << "Using range-based for: ";for (const auto& item : arr) {std::cout << item << " ";}std::cout << std::endl;return 0;
}

例子2:二叉树的中序遍历迭代器

#include <iostream>
#include <stack>
#include <memory>template <typename T>
struct TreeNode {T value;std::shared_ptr<TreeNode> left;std::shared_ptr<TreeNode> right;TreeNode(T val) : value(val), left(nullptr), right(nullptr) {}
};template <typename T>
class BinaryTree {
private:std::shared_ptr<TreeNode<T>> root;public:BinaryTree() : root(nullptr) {}void setRoot(std::shared_ptr<TreeNode<T>> node) {root = node;}// 中序遍历迭代器class InOrderIterator {private:std::stack<std::shared_ptr<TreeNode<T>>> stack;std::shared_ptr<TreeNode<T>> current;void pushLeft(std::shared_ptr<TreeNode<T>> node) {while (node) {stack.push(node);node = node->left;}}public:explicit InOrderIterator(std::shared_ptr<TreeNode<T>> root) {current = nullptr;pushLeft(root);if (!stack.empty()) {current = stack.top();stack.pop();}}T& operator*() const {return current->value;}InOrderIterator& operator++() {if (current->right) {pushLeft(current->right);}if (stack.empty()) {current = nullptr;} else {current = stack.top();stack.pop();}return *this;}bool operator!=(const InOrderIterator& other) const {return current != other.current;}bool hasNext() const {return current != nullptr;}};InOrderIterator begin() {return InOrderIterator(root);}InOrderIterator end() {return InOrderIterator(nullptr);}
};// 使用示例
int main() {// 创建二叉树: //       1//      / \//     2   3//    / \//   4   5auto root = std::make_shared<TreeNode<int>>(1);root->left = std::make_shared<TreeNode<int>>(2);root->right = std::make_shared<TreeNode<int>>(3);root->left->left = std::make_shared<TreeNode<int>>(4);root->left->right = std::make_shared<TreeNode<int>>(5);BinaryTree<int> tree;tree.setRoot(root);std::cout << "In-order traversal: ";for (auto it = tree.begin(); it.hasNext(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

例子3:STL风格的迭代器适配器

#include <iostream>
#include <vector>
#include <iterator>// 过滤迭代器:只返回满足条件的元素
template <typename Iterator, typename Predicate>
class FilterIterator {
private:Iterator current;Iterator end;Predicate predicate;void advanceToNextValid() {while (current != end && !predicate(*current)) {++current;}}public:FilterIterator(Iterator begin, Iterator end, Predicate pred): current(begin), end(end), predicate(pred) {advanceToNextValid();}FilterIterator& operator++() {if (current != end) {++current;advanceToNextValid();}return *this;}typename std::iterator_traits<Iterator>::value_type operator*() const {return *current;}bool operator!=(const FilterIterator& other) const {return current != other.current;}bool operator==(const FilterIterator& other) const {return current == other.current;}
};// 辅助函数创建过滤迭代器
template <typename Iterator, typename Predicate>
FilterIterator<Iterator, Predicate> make_filter_iterator(Iterator begin, Iterator end, Predicate pred) {return FilterIterator<Iterator, Predicate>(begin, end, pred);
}int main() {std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};// 定义谓词:只返回偶数auto isEven = [](int n) { return n % 2 == 0; };std::cout << "Even numbers: ";auto begin = make_filter_iterator(numbers.begin(), numbers.end(), isEven);auto end = make_filter_iterator(numbers.end(), numbers.end(), isEven);for (auto it = begin; it != end; ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

例子4:支持多种遍历方式的集合

#include <iostream>
#include <vector>
#include <algorithm>template <typename T>
class CustomCollection {
private:std::vector<T> data;public:void add(const T& item) {data.push_back(item);}// 前向迭代器class ForwardIterator {private:typename std::vector<T>::iterator it;public:explicit ForwardIterator(typename std::vector<T>::iterator iter) : it(iter) {}ForwardIterator& operator++() {++it;return *this;}T& operator*() const {return *it;}bool operator!=(const ForwardIterator& other) const {return it != other.it;}};// 反向迭代器class ReverseIterator {private:typename std::vector<T>::reverse_iterator it;public:explicit ReverseIterator(typename std::vector<T>::reverse_iterator iter) : it(iter) {}ReverseIterator& operator++() {++it;return *this;}T& operator*() const {return *it;}bool operator!=(const ReverseIterator& other) const {return it != other.it;}};ForwardIterator begin() {return ForwardIterator(data.begin());}ForwardIterator end() {return ForwardIterator(data.end());}ReverseIterator rbegin() {return ReverseIterator(data.rbegin());}ReverseIterator rend() {return ReverseIterator(data.rend());}
};int main() {CustomCollection<int> collection;for (int i = 1; i <= 5; ++i) {collection.add(i);}std::cout << "Forward: ";for (auto it = collection.begin(); it != collection.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;std::cout << "Reverse: ";for (auto it = collection.rbegin(); it != collection.rend(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

总结
迭代器模式是C++中非常重要的设计模式,它:

提供统一的遍历接口:无论底层数据结构如何,都能使用相同的方式遍历

支持多种遍历算法:可以根据需要实现不同的遍历策略

符合开闭原则:添加新的遍历方式不需要修改现有代码

与STL完美集成:C++标准库大量使用迭代器模式

在实际开发中,迭代器模式常用于:

自定义容器的实现

复杂数据结构的遍历

数据过滤和转换操作

提供与STL算法兼容的接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94052.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94052.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

epoll 陷阱:隧道中的高级负担

上周提到了 tun/tap 转发框架的数据通道结构和优化 tun/tap 转发性能优化&#xff0c;涉及 RingBuffer&#xff0c;packetization 等核心话题。我也给出了一定的数据结构以及处理逻辑&#xff0c;但竟然没有高尚的 epoll&#xff0c;本文说说它&#xff0c;因为它不适合。 epo…

微前端架构常见框架

1. iframe 这里指的是每个微应用独立开发部署,通过 iframe 的方式将这些应用嵌入到父应用系统中,几乎所有微前端的框架最开始都考虑过 iframe,但最后都放弃,或者使用部分功能,原因主要有: url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。 UI 不同…

SQL Server更改日志模式:操作指南与最佳实践!

全文目录&#xff1a;开篇语**前言****摘要****概述&#xff1a;SQL Server 的日志模式****日志模式的作用****三种日志模式**1. **简单恢复模式&#xff08;Simple&#xff09;**2. **完整恢复模式&#xff08;Full&#xff09;**3. **大容量日志恢复模式&#xff08;Bulk-Log…

git的工作使用中实际经验

老输入烦人的密码 每次我git pull的时候都要叫我输入三次烦人的密码&#xff0c;问了deepseek也没有尝试成功 出现 enter passphrase for key ‘~/.ssh/id_rsa’ 的原因: 在生成key的时候,没有注意,不小心设置了密码, 导致每次提交的时候都会提示要输入密码, 也就是上面的提示…

科技赋能,宁夏农业绘就塞上新“丰”景

在贺兰山的巍峨身影下&#xff0c;在黄河水的温柔滋养中&#xff0c;宁夏这片古老而神奇的土地&#xff0c;正借助农业科技的磅礴力量&#xff0c;实现从传统农耕到智慧农业的华丽转身&#xff0c;奏响一曲科技与自然和谐共生的壮丽乐章。一、数字农业&#xff1a;开启智慧种植…

imx6ull-驱动开发篇36——Linux 自带的 LED 灯驱动实验

在之前的文章里&#xff0c;我们掌握了无设备树和有设备树这两种 platform 驱动的开发方式。但实际上有现成的&#xff0c;Linux 内核的 LED 灯驱动采用 platform 框架&#xff0c;我们只需要按照要求在设备树文件中添加相应的 LED 节点即可。本讲内容&#xff0c;我们就来学习…

深度学习中主流激活函数的数学原理与PyTorch实现综述

1. 定义与作用什么是激活函数&#xff1f;激活函数有什么用&#xff1f;答&#xff1a;激活函数&#xff08;Activation Function&#xff09;是一种添加到人工神经网络中的函数&#xff0c;旨在帮助网络学习数据中的复杂模式。类似于人类大脑中基于神经元的模型&#xff0c;激…

Linux高效备份:rsync + inotify实时同步

一、rsync 简介 rsync&#xff08;Remote Sync&#xff09;是 Linux 系统下的数据镜像备份工具&#xff0c;支持本地复制、远程同步&#xff08;通过 SSH 或 rsync 协议&#xff09;&#xff0c;是一个快速、安全、高效的增量备份工具。二、rsync 特性 支持镜像保存整个目录树和…

一种通过模板输出Docx的方法

起因在2个群里都有网友讨论这个问题&#xff0c;俺就写了一个最简单的例子。其实&#xff0c;我们经常遇到一些Docx的输出的需求&#xff0c;“用模板文件进行处理”是最简单的一个方法&#xff0c;如果想预览也简单 DevExpress 、Teleric 都可以&#xff0c;而且也支持 Web 、…

探索 List 的奥秘:自己动手写一个 STL List✨

&#x1f4d6;引言大家好&#xff01;今天我们要一起来揭开 C 中 list 容器的神秘面纱——不是直接用 STL&#xff0c;而是亲手实现一个简化版的 list&#xff01;&#x1f389;你是不是曾经好奇过&#xff1a;list 是怎么做到高效插入和删除的&#xff1f;&#x1f50d;迭代器…

mysql占用高内存排查与解决

mysql占用高内存排查-- 查看当前全局内存使用情况&#xff08;需要启用 performance_schema&#xff09; SELECT * FROM sys.memory_global_total; -- 查看总内存使用 SELECT * FROM sys.memory_global_by_current_bytes LIMIT 10; -- 按模块分类查看内存使用排行memory/perfor…

构建真正自动化知识工作的AI代理

引言&#xff1a;新一代生产力范式的黎明 自动化知识工作的人工智能代理&#xff08;AI Agent&#xff09;&#xff0c;或称“智能体”&#xff0c;正迅速从理论构想演变为重塑各行各业生产力的核心引擎。这些AI代理被定义为能够感知环境、进行自主决策、动态规划、调用工具并持…

青少年机器人技术(四级)等级考试试卷-实操题(2021年12月)

更多内容和历年真题请查看网站&#xff1a;【试卷中心 -----> 电子学会 ----> 机器人技术 ----> 四级】 网站链接 青少年软件编程历年真题模拟题实时更新 青少年机器人技术&#xff08;四级&#xff09;等级考试试卷-实操题&#xff08;2021年12月&#xff09; …

最新短网址源码,防封。支持直连、跳转。 会员无广

最新短网址源码&#xff0c;防封。支持直连、跳转。 会员无广告1.可将长网址自动缩短为短网址&#xff0c;方便记忆和使用。2.短网址默认为临时有效&#xff0c;可付费升级为永久有效&#xff0c;接入支付后可自动完成&#xff0c;无需人工操作。3.系统支持设置图片/文字/跳转页…

缓存-变更事件捕捉、更新策略、本地缓存和热key问题

缓存-基础知识 熟悉计算机基础的同学们都知道&#xff0c;服务的存储大多是多层级的&#xff0c;呈现金字塔类型。通常来说本机存储比通过网络通信的外部存储更快&#xff08;现在也不一定了&#xff0c;因为网络传输速度很快&#xff0c;至少可以比一些过时的本地存储设备速度…

报表工具DevExpress .NET Reports v25.1新版本亮点:AI驱动的扩展

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 DevExpress Reporting控件日前正式发布了v25.1…

kubernetes中pod的管理及优化

目录 2 资源管理方式 2.1 命令式对象管理 2.2 资源类型 2.2.1 常用的资源类型 2.2.2 kubectl常见命令操作 2.3 基本命令示例 2.4 运行和调试命令示例 2.5 高级命令示例 3 pod简介 3.1 创建自主式pod&#xff08;生产环境不推荐&#xff09; 3.1.1 优缺点 3.1.2 创建…

解释一下,Linux,shell,Vmware,Ubuntu,以及Linux命令和shell命令的区别

Linux 操作系统概述Linux 是一种开源的类 Unix 操作系统内核&#xff0c;由 Linus Torvalds 于 1991 年首次发布。作为现代计算的基础设施之一&#xff0c;它具有以下核心特征&#xff1a;多用户多任务特性允许多个用户同时操作系统资源&#xff0c;而模块化设计使其能够适应从…

Windows 系统中,添加打印机主要有以下几种方式

在 Windows 系统中,添加打印机主要有以下几种方式,我将从最简单到最复杂为您详细介绍。 方法一:自动安装(推荐首选) 这是 Windows 10 和 Windows 11 中最简单、最现代的方法。系统会自动搜索网络(包括无线和有线网络)上可用的打印机并安装驱动程序。 操作步骤: 进入…

Mixture of Experts Guided by Gaussian Splatters Matters

Mixture of Experts Guided by Gaussian Splatters Matters: A new Approach to Weakly-Supervised Video Anomaly Detection ICCV2025 https://arxiv.org/pdf/2508.06318 https://github.com/snehashismajhi/GS-MoEAbstract 视频异常检测&#xff08;VAD&#xff09;是一项具有…