• c++ stl的迭代器部分功能可以这样实现


    前言

    本文首先写了我理解的迭代器的部分功能,然后写如何实现这些功能,纯属是个人理解和实现,并不代表stl的迭代器就是那样实现的。本人还未阅读stl源码,不知道stl是如何实现的。为此特别说明,我不希望误导stl学习者。

    我理解的c++ stl容器迭代器的部分功能

    功能1:是对容器元素的指针

    星号运算符

    假设vector list中某个元素list[2]的指针是point,迭代器器是iter。
    我们可以这样使用指针:

    int value=*point;
    *point=3;    //这会导致list[2]=3;
    
    • 1
    • 2

    我们可以像指针一样使用迭代器:

    int value=*iter; 
    *iter=3;     //这会导致list[2]=3;
    
    • 1
    • 2

    ->运算符

    定义一个简单的类

    class demo
    {
    	public:
    	int v1;
    	int v2;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    假设vector list2的一个元素list2[2]是{1,2}。它的指针是point,它的迭代器是iter。
    我们可以这样使用指针

    int v1=point->v1;
    point->v1=3;   //list2[2].v1=3;
    
    • 1
    • 2

    我们可以以同样的方式使用迭代器

    int v1-iter->v1;
    point->v1=3;   //list2[2]=3;
    
    • 1
    • 2

    功能1总结

    我们可以把迭代器理解为指向某个元素的指针,然后可以像使用指针一样使用这个迭代器。

    功能2:容器元素的成员的子集

    树是节点的容器。节点是树的元素。节点有很多成员,有很多成员我们需要提供给用户,有些成员需要对用户屏蔽。通过迭代器就可以做到这点。用户从来不直接访问具体节点,他们最多只能获取节点对应的迭代器。迭代器里面有节点部分成员的引用。访问或者修改迭代器的成员,实际上就是访问和修改节点的成员。节点中要对用户屏蔽的成员,我们不要让他出现在迭代器成员里面即可。

    功能3:容器元素的成员的访问权限

    有时我们希望用户能够访问节点的部分信息,这部分信息中,又有一部分希望用户只能读不能写,一部分允许用户读和写。迭代器可以实现这样的功能。用户从来不能直接访问容器元素,他们只能访问容器元素的迭代器。我们在迭代器把只能读不能写的节点成员引用加上const。用户就不能修改了,但仍然可读。

    功能4:容器的成员函数可以通过迭代器获取元素的地址,但用户不能

    用户交给容器一个元素的迭代器,希望容器对这个元素做一些操作,由于迭代器里面是没有节点的全部信息的(迭代器是容器元素成员的子集),可能导致某些动作无法完成。幸运的是,容器可以通过迭代器获取它所指向的元素的地址。这个是个特殊权限。因为我们不希望用户可以这样做,不希望用户获取节点的全部信息。

    对上面4个功能的实现

    直接上代码,后面有对代码的解读和说明:

    #include 
    
    using namespace std;
    class my_node;  //前部申明
    class rb_tree;
    
    class my_iterator
    {
        public:
        const int &key;
        int &value;
    
        my_iterator(int& _key,int& _value):key(_key),value(_value)
        {
        }
        my_iterator* operator->()
        {
            return this;
        }
        int& operator*()
        {
            return value;
        }
        private:
        my_node *node;
        friend rb_tree;
    };
    class my_node
    {
        public:
        int key;
        int value;
        my_node *left;
        my_node *right;
        my_iterator iter;
        my_node():iter(key,value){key=1;value=1;}
    };
    
    
    class rb_tree
    {
    public:
        void rb_delete(my_iterator iter)
        {
            my_node *node=iter->node; //通过迭代器获取迭代器对应的节点。只有容器的方法可以获取。其他地方获取容器方法是不行的。
        }
        
    
    };
    
    int main()
    {
        my_node a;
        my_iterator aiter=a.iter;
        cout<<"通过迭代器获取节点的key:"<<aiter->key<<endl;
        //aiter.key=2;    //若取消注释,编译不通过,因为只能通过迭代器读key,不能修改key
        //my_node *ap=aiter->node;  //若取消注释,编译不通过,因为只有rb_tree的成员函数可以通过迭代器获取节点。
        cout<<"通过迭代器获取节点的value:"<<aiter->value<<endl;
        *aiter=2;//通过迭代器重载的*运算符修改节点的value值。
        cout<<"通过迭代器重载的*运算符修改节点的value值:"<<a.value<<endl;
        aiter->value=3;
        cout<<"通过迭代器修改节点的value值:"<<a.value<<endl;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    前部申明

    由于节点类中有一个迭代器成员,所以迭代器类必须在节点类前定义。又由于迭代器类中有一个节点类对象指针。所以必须在迭代器类前面对节点类做前部申明。前部申明之后,类申明之前,该类只能以指针或者引用的方式出现。

    迭代器的类成员是节点类部分成员的引用

    这样,主函数修改迭代器的类成员,实际上就是修改节点。
    迭代器中的key前面加了const,使得用户只能读key,不能修改key。

    由于把引用作为类成员,所以该类不能有缺省的构造函数,必须自己实现构造函数,并在初始化列表中,完成对引用类成员的初始化,而且,构造函数的参数也必须是引用类型。否则,编译会报错。

    重载->运算符

    为了使得迭代器能够像指针一样使用,重载了->运算符,这是一个单目运算符,返回指向对象本身的指针。

    重载*运算符

    这里返回的是节点 value字段的引用,使得迭代器像指向节点value字段的指针一样。

    my_node指针private

    节点迭代器与节点一一对应,体现在迭代器里面有一个node的指针。设置为private,使得用户不能通过迭代器对象获取节点指针。但又申明tree为友元。这样树(节点的容器)就可以访问迭代器的private成员,就可以过去迭代器对应的节点的指针了。

  • 相关阅读:
    38_final关键字
    【C++动态规划 多重背包】1774. 最接近目标价格的甜点成本|1701
    马尔可夫链文本生成预测
    MySql无法连接本地地址localhost
    maven报错:[ERROR] 不再支持源选项 7。请使用 8 或更高版本。
    华为数据中心机房集成解决方案
    Apache Airflow (三) :Airflow WebUI操作介绍
    25. Java 锁机制之 Condition 接口
    04-栈(Stack)结构应用分析
    Kvaser Leaf light HS v2 | 如何使用Excel发送和接收CAN报文数据
  • 原文地址:https://blog.csdn.net/ld_long/article/details/126611061