【C++】从特定容器的迭代器到实现统一的抽象迭代器接口类(Iterator)

【C++】深入理解迭代器(Iterator) C++ 是一门功能强大的编程语言,其标准库(STL, Standard Template Library)提供了多种高效的工具来处理数据。其中,迭代器(Iterator)是一种极为重要的工具,可以帮助开发者优雅地操作容器,遍历、访问和修改数据。迭代器的作用类似于指针,但比指针更强大和灵活。本文将以 std::string 为例,结合代码和图示,从基本概念到实际应用,带领读者深入理解 C++ 中迭代器的核心功能和用法。 2025.1.8-✍210min 阅读详情

迭代器(Iterator)概念详解

📌 什么是迭代器?

迭代器是一种抽象的设计模式,它提供了一种统一的方式来访问和遍历容器中的元素。一个迭代器可以是一个任意的对象,它指向某个范围内的元素(如数组、链表、树等),并通过实现一些基本操作来逐个访问这些元素。


🧩 迭代器的简单例子

示例 1:用下标变量模拟迭代器功能

int a[5] = {1, 2, 3, 4, 5};
int sum = 0;

for (int i = 0; i < 5; i++) {
    sum += a[i];
}
  • 变量 i 是一个整型索引,但它起到了类似迭代器的作用 —— 遍历数组中的每个元素。

示例 2:用指针模拟迭代器功能

Node *p = l.head;
while (p) {
    // 使用 p->data 访问当前节点的数据
    p = p->next;
}
  • 指针 p 遍历了一个链表中的所有节点,它也具有类似于迭代器的功能。

🛠️ 如何为特定容器实现迭代器?

对于一个特定的容器类型(自定义类型),我们可以设计并实现一个专门的迭代器类:

✅ 只能用于容器Array的迭代器实现

#include <iostream>
#include <ostream>

using namespace std;

// 模板类 Array:支持非类型参数 n,表示数组的固定容量
template<typename T, int n>		
class Array
{
private:
    T* arr;       // 动态分配的数组指针
    int capcity;  // 数组容量(最大可容纳元素个数)
    int size;     // 当前实际元素个数

public:
    // 构造函数:根据模板参数 n 分配空间
    Array() : arr(nullptr), capcity(n), size(0)
    {
        if (capcity > 0)
        {
            arr = new T[capcity];
        }
    }

    // 拷贝构造函数:深拷贝
    Array(const Array<T, n>& a) : arr(nullptr), capcity(a.capcity), size(a.size)
    {
        if (capcity > 0)
        {
            arr = new T[capcity];

            for (int i = 0; i < size; ++i)
            {
                (*this)[i] = a[i];  // 使用下标操作符赋值
            }
        }
    }

    // 析构函数:释放动态分配的空间
    ~Array()
    {
        if (arr)
        {
            delete[] arr;
        }
    }

    // 下标运算符重载(非 const 版本)
    T& operator[](const int& i)
    {
        if (i >= 0 && i < size)
        {
            return arr[i];
        }
    }

    // 下标运算符重载(const 版本)
    const T& operator[](const int& i) const
    {
        if (i >= 0 && i < size)
        {
            return arr[i];
        }
    }

    // 插入元素到数组末尾
    bool insert(const T& d)
    {
        if (size >= capcity)
        {
            return false;  // 容量已满,插入失败
        }

        arr[size++] = d;
        return true;
    }

    // 获取当前数组中实际元素个数
    int length(void) const
    {
        return size;
    }

    // << 输出运算符重载(友元函数)
    template<typename T1, int n1>
    friend ostream& operator<<(ostream& o, const Array<T1, n1>& a);
    
    // 迭代器类:用于遍历 Array 数组中的元素
    class ArrayIterator
    {
    private:
        T* _arr;      // 指向数组起始位置
        int _size;    // 遍历范围内的元素个数
        int index;    // 当前下标

    public:
        ArrayIterator(T* _start, int _s) : _arr(_start), _size(_s), index(0)
        {}

        // 将迭代器重置为指向第一个元素
        void begin(void)
        {
            index = 0;
        }

        // 返回当前元素引用
        T& operator*(void)
        {
            return _arr[index];
        }

        // 前缀自增运算符:移动到下一个元素
        ArrayIterator& operator++()
        {
            index++;
            return *this;
        }

        // 判断是否到达结尾
        bool is_end(void)
        {
            return index == _size;
        }
    };

    // 获取默认迭代器(从头开始,遍历全部元素)
    ArrayIterator get_Iterator(void)
    {
        return ArrayIterator(arr, size);
    }

    // 获取指定起点和数量的迭代器
    ArrayIterator get_Iterator(const int& first, const int& num)
    {
        return ArrayIterator(arr + first, num);
    }
};

// << 输出运算符重载实现
template<typename T, int n>
ostream& operator<<(ostream& o, const Array<T, n>& a)
{
    for (int i = 0; i < a.length(); ++i)
    {
        o << a[i] << "  ";
    }
    o << endl;
    return o;
}

int main()
{
    // 创建一个容量为10的整型数组
    Array<int, 10> a;

    // 插入7个元素
    a.insert(1);
    a.insert(3);
    a.insert(5);
    a.insert(7);
    a.insert(9);
    a.insert(11);
    a.insert(13);

    // 输出整个数组
    cout << a << endl;
    // 输出:
    // 1  3  5  7  9  11  13  

    cout << "--------------------" << endl;

    // 获取默认迭代器
    auto it = a.get_Iterator();

    // 使用迭代器遍历数组
    for (it.begin(); !it.is_end(); ++it)
    {
        cout << *it << "  ";
    }
    cout << endl;
    // 输出:
    // 1  3  5  7  9  11  13  

    // 获取偏移1、长度6的迭代器
    Array<int, 10>::ArrayIterator itr = a.get_Iterator(1, 6);
    for (itr.begin(); !itr.is_end(); ++itr)
    {
        cout << *itr << "  ";
    }
    cout << endl;
    // 输出:
    // 3  5  7  9  11  13  
}

🔁 迭代器的工作原理

迭代器的本质是封装了“如何访问数据”的逻辑。它不关心底层容器的具体结构(数组、链表、哈希表等),而是通过统一接口来访问元素。

  • 在软件构建中,集合对象的内部结构常常变化各异, 如:某种集合可能是数组实现,也可能是用链表实现的 …
  • 对于这些集合对象, 我们希望在不暴露其内部结构的同时, 可以让外部用户透明的去访问其中包含的元素
  • 同时 这种"透明遍历" 也为同一个算法在多个集合对象进行操作的提供了可能 ,使用面向对象技术将这种遍历机制抽象为 “迭代器对象” ,为遍历"变化中的集合对象"提供了一种很好的方式
  • 迭代器模式:
    提供一种方法 顺序访问一个聚合对象中的每一个元素,而又不暴露该对象的内部结构的表示

现在将之前实现的 ArrayIterator 类,改写为从一个统一的抽象迭代器接口类 Iterator<T> 派生出来。


纯抽象类的迭代器接口

✅ 第一步:定义基类

template<typename T>
class Iterator {
public:
    virtual void begin() = 0;           // 将迭代器重置到起始位置
    virtual bool end() const = 0;       // 判断是否到达结束位置
    virtual Iterator& operator++() = 0; // 前缀 ++ 运算符,移动到下一个元素
    virtual T& operator*() const = 0;   // 解引用操作符,返回当前元素的引用

    virtual ~Iterator() = default;      // 虚析构函数,确保派生类析构安全
};

✅ 第二步:修改 ArrayIterator `

我们将原来的嵌套类 ArrayIterator 改写为继承自 Iterator<T>,并实现所有纯虚函数。

📦 定义如下:

// 数组Array的"迭代器类",继承自 Iterator<T>
template<typename T>
class ArrayIterator : public Iterator<T> {
private:
    T* _arr;         // 指向遍历范围的首元素
    int _size;       // 遍历范围内元素个数
    int index;       // 当前下标

public:
    ArrayIterator(T* start, int size)
        : _arr(start), _size(size), index(0) {}

    // 重置为第一个元素
    void begin() override {
        index = 0;
    }

    // 是否到达末尾
    bool end() const override {
        return index == _size;
    }

    // 前缀 ++it
    Iterator<T>& operator++() override {
        ++index;
        return *this;
    }

    // *it 返回当前元素的引用
    T& operator*() const override {
        return _arr[index];
    }
};

✅ 第三步:更新 Array 类

ArrayIterator<T> get_Iterator() {
    return ArrayIterator<T>(arr, size);
}

✅ 第四步:使用

使用统一的接口:

int main() {
    Array<int, 10> a;

    a.insert(1);
    a.insert(3);
    a.insert(5);
    a.insert(7);
    a.insert(9);
    a.insert(11);
    a.insert(13);

    cout << a << endl;
    cout << "--------------------" << endl;

    // 使用统一的迭代器接口
    ArrayIterator<int> it = a.get_Iterator();

    for (it.begin(); !it.end(); ++it) {
        cout << *it << "  ";
    }
    cout << endl;
    // 输出: 1  3  5  7  9  11  13  

    // 使用偏移迭代器
    ArrayIterator<int> itr = a.get_Iterator(1, 6);

    for (itr.begin(); !itr.end(); ++itr) {
        cout << *itr << "  ";
    }
    cout << endl;
    // 输出: 3  5  7  9  11  13  
}

🎯 补充说明

特性说明
统一接口不同容器都可以使用相同的迭代器接口进行访问,便于泛型编程。
STL 支持C++ STL 中几乎所有容器都支持迭代器,例如 std::vector, std::list, std::map 等。
增强可维护性容器与算法分离,提高了代码的复用性和可维护性。
避免越界访问迭代器可以通过边界检查等方式提升安全性。
C++ STL六大组件-4-Iterator(迭代器) 视C++为一个语言联邦: 理解C++的全貌,学习C++的编程范式:过程/面向对象/函数式/元编程/泛型编程。 尽量以const/enum/inline替换#define:对于单纯的常量,最好用const对象/enums来替换#define,对于形似函数的宏,最好用inline函数替换#define. 尽可能使用const:const可以用于任何作用域内的对象/函数参数/函数返回类型/成员函数本体。可以帮助避免出错。 确定对象被使用前已经先被初始化:读取未初始化的值会导致不明确的行为。 了解C++ . 阅读详情

相关推荐

C++标准模板库 迭代器 iterator 详解(一)

#include #include #include #include #include //copy using namespace std; template inline void print (const T& coll, const char* optcstr="") { typename T::const_iterator pos; std::cout

聚精会神搞建设 2802

C++:使自定义类支持迭代器

概述 在 C++ 中,链表迭代器是一种用来遍历链表(如 std::list)元素的工具。链表是一种数据结构,其中每个元素(节点)包含一个数据值和一个指向下一个节点的指针。链表迭代器允许以类似于数组的方式访问链表中的元素,但不需要直接操作指针。 链表迭代器的作用 访问元素:链表迭代器使你能够顺序访问链表中的每个元素,就像在数组中遍历元素一样。 遍历链表:通过迭代器,你可以在链表中前进或后...

weixin_42717586的博客 242

C++ 头文件系列(iterator)

简介 该头文件围绕迭代器展开,定义了一系列与迭代器有关的概念,但最最最重要的一点就是----它和其它容器一起实现了C++容器的Iterator设计模式。 Iterators are a generalization of pointers that allow a C++ program to work with different data structures(containers

爱无止尽的博客 5352

C++——实现一个简单的迭代器

迭代器的实现

weixin_67452474的博客 4741

Weblogic安装与部署

27.免密登录,在目录Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\AdminServer和Oracle\Middleware\Oracle_Home\user_projects\domains\base_domain\servers\Server-TA目录下,新建security\boot.properties文件,13.点击新建按钮,填写服务器名称,服务器监听地址,再点击下一步,最后点击完成。

m0_46259466的博客 6635

触摸延时灯课程设计

Multisim源文件下载: 实验名称:­­­­­­­­­­­­­­­­­­­ 课程设计1:触摸延时灯仿真设计 设计要求: 利用单稳态触发器设计触控延时灯,要求利用触发波形的边沿模拟触控点实现触发,触发后3秒灯亮,灯可以亮的时间可在5-10秒之间可调。 设计思路: 利用集成单稳态触发器CD4098设计简易的触摸延时灯电路。应用CD4098可以实现脉冲延时,原理图如下。4脚未触发信号输入端,可通过比较器对触摸产生的信号进行比较后再产生触发信号,使触发准确度得以提高。...

m0_54240221的博客 1万+

模拟实现C++中的ListIterator函数

#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; template<class T> struct ListNode { ListNode(const T& data = T()) : _pNext(NULL) , _pPre(NULL) , _data(data)

痴心不改的博客 679

从仿真到实机:四足机器人控制算法的全流程验证框架

本文系统阐述了四足机器人从仿真到实机的全流程验证框架。针对仿真与实机环境的巨大差异,文章详细介绍了在MuJoCo等高保真仿真环境中的建模、算法迭代与压力测试方法,并重点解析了通过硬件抽象层和中间件搭建通往实机的关键桥梁。最后,提供了实机部署的安全清单与调试策略,旨在帮助开发者构建可重复、风险可控的算法验证闭环,提升算法在真实世界中的鲁棒性与可靠性。

lilh34434的博客 381

【C++】迭代器的类型

  迭代器本质上是什么?当然,任何一种特定的迭代器都是某种类型的对象。不过,迭代器的类型非常多,毕竟每种迭代器都是与某种特定容器类型相关联的。它需要保存一些必要的信息,以便我们对容器执行某些特定的任务。因此,有多少种容器就有多少种迭代器,有多少中特殊要求就有多少种迭代器。   vector的迭代器可能就是一个普通指针,因为就引用vector中的元素而言指针再恰当不过了:或者,vecto...

dnhm47322的博客 1482

飞牛NAS挂载115网盘避坑指南:为什么你的大文件总是传输失败?

本文深入解析了在飞牛NAS上通过AList挂载115网盘时,大文件传输失败的深层原因,包括风控机制、网络协议及兼容性问题。文章提供了从基础排查到高阶优化的系统性解决方案,并建议采用Kopia分片备份等终极策略,以实现稳定可靠的云端数据流转。

weixin_29306011的博客 1681

刷机维修进阶教程-----adb禁用错了系统app导致无法开机 如何保数据无损恢复机型

在刷机维修过程中 。我们会遇到一些由于客户使用adb指令来禁用手机app而导致手机无法开机进入系统的故障机型。通常此类问题机型有好几种解决方法。但如果客户需要保数据来恢复机型。其实操作也是很简单的.还有类似误删除应用导致不开机等等如何保数据。  通过博文了解💝💝💝    1💝💝💝----adb禁用或者删除系统app导致无法开机的几种解决方法 2💝💝💝----如何保数据来无损恢复机型 3💝💝💝----其他保数据解决系统类故障无法开机的步骤解析

小马哥的专栏 1350

编写自己的迭代器

自定义迭代器必须提供iterator_traits的五种特性,分别是迭代器类型、元素类型、距离类型、指针类型与reference类型。 这里我们继承标准库提供的iterator<>即可。 代码如下: 1 #ifndef ITERATOR_H 2 #define ITERATOR_H 3 #include <iterator> 4 5 temp...

weixin_34092455的博客 207

知识存储之Apache Jena

知识图谱的存储可以分为基于表结构的存储和基于图结构的存储。1️⃣基于表结构的存储基于表结构的存储利用二维的数据表对知识图谱中的数据进行存储。根据不同的设计原则,知识图谱可以具有不同的表结构:💨知识图谱实质上是一个个的三元组,一种简单直接的存储方式是设计一张三元组表用于存储所有三元组,有不少比较成熟的产品利用该形式存储知识图谱,包括Jena、Oracle、Virtuoso等。💨为每种类型构建一张表,同一类型的实例存放在相同的表中。

Puzzle的博客 6064

list 迭代器:C++ 容器封装的 “行为统一” 艺术

在C++标准库中,std::list是双向链表的容器,我们日常用就能方便地插入删除,但它的底层实现究竟是什么样的?尤其是迭代器(iterator),为什么it!=lst.end();++it)可以统一操作链表?今天,我基于一个精简版mini_list的实现,重点解析迭代器封装的底层思想,带大家从零实现并理解list容器。在mini_list中,通过实例化public:// 可写迭代器:ref=T&,ptr=T*// 只读迭代器:ref=const T&,ptr=const T*// ...

Vect__的博客 2328

如何合法抓取TikTok视频信息和评论:完整Python爬虫教程

尽管TikTok没有开放的公共API来直接抓取视频内容和评论,开发者仍然可以通过合法的方式使用第三方API工具来获取公开数据。无论使用什么工具,都应当严格遵守TikTok的使用条款和当地的隐私法规,确保数据抓取行为符合规定。通过本文介绍的TikTok-Api库和Python技术,你可以合法地抓取公开的视频信息和评论,并进行数据存储与分析。使用这些技术时,务必确保抓取行为不会侵犯用户隐私,并遵守平台的API使用规定。

2201_76125261的博客 1709

PyCharm配置SSH和SFTP远程连接服务器

关于这篇博文,主要因为公司企业都是通过本地测试,同步到服务器进行跑动,舍友看着同事丝滑的操作,让我做个教程。本着钻研的精神,写下了这篇博客记录 关于pycharm这个软件,只有专业版才有远程连接的这个配置,社区版没有(同事一再强调要专业版,学生认证还可申请免费) 关于SSH和SFTP都是一种协议 具体知识点补充可看我这篇文章: 【计算机网络】常见面试题集锦(全) SSH:提供安全通道进行远程登录 SFTP协议可以远程文件传输获取等,数据的安全传输主要由SSH连接提供

码农研究僧的博客 5533

C++ 迭代器iterator

在 C++ 中,迭代器(iterator)是一种通用的抽象概念,用于在容器(如std::liststd::map等)中遍历和访问元素。迭代器提供了一种统一的接口,使得不同类型的容器可以以相似的方式进行遍历和操作。大多数 C++ 容器都提供了迭代器,用于遍历容器中的元素。例如,和std::deque提供了随机访问迭代器,std::list提供了双向迭代器,std::set和std::map提供了双向迭代器。

2201_75772333的博客 2128

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

迭代器iterator是C++中用于遍历容器中元素的对象

迭代器的使用通常伴随着容器的.begin()和.end()成员函数,这两个函数分别返回指向容器第一个元素和尾后元素的迭代器。

book_dw5189的博客 1373

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

迭代器修改元素_C++ STL六大组件4Iterator(迭代器)

C++ STL 迭代器STL概述的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但这种分离确实使得算法变得非常通用。例如,由于函数是完全通用的,你可以用它来操作几乎任何数据集合,包括链表,容器和数组。在C++ STL 中,对容器中数据的读和写,是通过迭代器完成的,扮演着容器和算法之间的胶合剂。只要容器提供迭代器的接口,同一套算法代码可以利用在完全不同的容器中,这是抽象思想的经...

weixin_39880337的博客 1246

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C++ STL 迭代器 iterator

几乎所有标准库容器都定义了各自的 iterator 类型,所有当使用特定容器的时候,不需要包含特殊的 iterator 头文件。不过一些特殊的 iterator,例如 reverse iterator,以及若干个辅助函数被定义于 头文件 <iterator> 中。

2401_83484142的博客 1205

c++迭代器(Iterator)

随机访问迭代器是一种迭代器类型,它比双向迭代器更加灵活和强大,支持双向遍历容器中的元素,也支持任意位置的随机访问,是STL中最强大和最高效的迭代器类型。另外,随机访问迭代器还可以使用[]操作符访问容器中的元素,支持迭代器之间的比较,以及其他STL迭代器所支持的操作,例如解引用、赋值、拷贝等。C++ STL标准库中的一些容器和算法都支持输出迭代器,例如std::vector,std::list,std::set等容器,std::copy(),std::transform()等算法都可以使用输出迭代器。

XXUZZWZ的博客 1533

C++之迭代器(Iterator)模式

0. 简介 迭代器模式是一种行为设计模式, 它可以有效管理数据流动的同时,让用户能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。 迭代器通常会提供一个获取集合元素的基本方法。 客户端可不断调用该方法直至它不返回任何内容, 这意味着迭代器已经遍历了所有元素。 1. 迭代器模式示意图 迭代器模式的使用方法和c11的迭代器使用方法类似,这是我们会根据我们的需求去建立迭代器模型。 抽象容器(Collection):一般是一个接口,提供一个iterator()方法,例如Collect

lovely_yoshino的博客 6310

C++STL中的迭代器iterator的作用和使用方法

作用: 迭代器(iterator)是一种抽象的设计理念,通过迭代器可以在不了解容器内部原理的情况下遍历容器。 除此之外,STL中迭代器一个最重要的作用就是作为容器(vector,list等)与STL算法的粘结剂,只要容器提供迭代器的接口,同一套算法代码可以利用在完全不同的容器中,这是抽象思想的经典应用。 使用: vector<int>::iterator it; vector<int> a; vector<int> b; for (it=a.beg.

马小超 4503

C++源码剖析——iterator

本文描述了llvm中libcxx的```iterator```的实现。

梦的灰色边沿... 970

C++STL的迭代器(iterator)

而是后一个位置(看图。

xinxin的博客 539

设计模式之迭代器模式(Iterator)的C++实现

迭代器模式(Iterator)的C++实现,泛型编程实现迭代器的C++实现。在软件开发过程中,操作的集合对象内部结构常常变化,在访问这些对象元素的同时,也要保证对象内部的封装性。迭代器模式提供了一种利用面向对象的遍历方法来遍历对象元素。迭代器模式通过抽象一个迭代器类,不同的对象继承自迭代器类,外部通过统一接口访问元素。面向对象实现的迭代器模式是在程序运行时,通过虚函数去操作对象元素;相比于C++中的泛型编程实现迭代器的运行性能较低(泛型编程是在编译时已确定访问的元素),所以建议使用泛型编程实现迭代器。

hanxiaoyong_的博客 1572
上一篇: 关于模板类的友元函数的运算符重载的问题
下一篇: 数据如何在各种网络硬件设备中流转
思路可以啊
博客等级 码龄6年 91粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值