迭代器模式與幾個經典的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
英文地址,請注明出處:http://en.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;是一項具有…