本文首先写了我理解的迭代器的部分功能,然后写如何实现这些功能,纯属是个人理解和实现,并不代表stl的迭代器就是那样实现的。本人还未阅读stl源码,不知道stl是如何实现的。为此特别说明,我不希望误导stl学习者。
假设vector
我们可以这样使用指针:
int value=*point;
*point=3; //这会导致list[2]=3;
我们可以像指针一样使用迭代器:
int value=*iter;
*iter=3; //这会导致list[2]=3;
定义一个简单的类
class demo
{
public:
int v1;
int v2;
}
假设vector
我们可以这样使用指针
int v1=point->v1;
point->v1=3; //list2[2].v1=3;
我们可以以同样的方式使用迭代器
int v1-iter->v1;
point->v1=3; //list2[2]=3;
我们可以把迭代器理解为指向某个元素的指针,然后可以像使用指针一样使用这个迭代器。
树是节点的容器。节点是树的元素。节点有很多成员,有很多成员我们需要提供给用户,有些成员需要对用户屏蔽。通过迭代器就可以做到这点。用户从来不直接访问具体节点,他们最多只能获取节点对应的迭代器。迭代器里面有节点部分成员的引用。访问或者修改迭代器的成员,实际上就是访问和修改节点的成员。节点中要对用户屏蔽的成员,我们不要让他出现在迭代器成员里面即可。
有时我们希望用户能够访问节点的部分信息,这部分信息中,又有一部分希望用户只能读不能写,一部分允许用户读和写。迭代器可以实现这样的功能。用户从来不能直接访问容器元素,他们只能访问容器元素的迭代器。我们在迭代器把只能读不能写的节点成员引用加上const。用户就不能修改了,但仍然可读。
用户交给容器一个元素的迭代器,希望容器对这个元素做一些操作,由于迭代器里面是没有节点的全部信息的(迭代器是容器元素成员的子集),可能导致某些动作无法完成。幸运的是,容器可以通过迭代器获取它所指向的元素的地址。这个是个特殊权限。因为我们不希望用户可以这样做,不希望用户获取节点的全部信息。
直接上代码,后面有对代码的解读和说明:
#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;
}
由于节点类中有一个迭代器成员,所以迭代器类必须在节点类前定义。又由于迭代器类中有一个节点类对象指针。所以必须在迭代器类前面对节点类做前部申明。前部申明之后,类申明之前,该类只能以指针或者引用的方式出现。
这样,主函数修改迭代器的类成员,实际上就是修改节点。
迭代器中的key前面加了const,使得用户只能读key,不能修改key。
由于把引用作为类成员,所以该类不能有缺省的构造函数,必须自己实现构造函数,并在初始化列表中,完成对引用类成员的初始化,而且,构造函数的参数也必须是引用类型。否则,编译会报错。
为了使得迭代器能够像指针一样使用,重载了->运算符,这是一个单目运算符,返回指向对象本身的指针。
这里返回的是节点 value字段的引用,使得迭代器像指向节点value字段的指针一样。
节点迭代器与节点一一对应,体现在迭代器里面有一个node的指针。设置为private,使得用户不能通过迭代器对象获取节点指针。但又申明tree为友元。这样树(节点的容器)就可以访问迭代器的private成员,就可以过去迭代器对应的节点的指针了。