C++迭代器实现原理(附带了Java)

本文探讨了C++和Java迭代器的实现原理,以Java的ArrayList为例介绍了迭代器如何统一调用不同容器的方法,然后详细解析了C++迭代器的实现,包括通过迭代器tag和template重载实现不同容器的编译器决策,强调了C++迭代器的性能优势和设计哲学。
摘要由CSDN通过智能技术生成

前言

只要用过C++的容器,相信大家对迭代器都不会陌生。它提供一种统一的接口形式来遍历相应的容器(例如数组,链表,map等)。

例子1:迭代器的遍历
利用迭代器遍历数组vector

vector<int> vi{ 1, 3, 5, 7, 9 };
for(auto it = vi.begin(); it != vi.end(); ++it) {
    cout<<*it<<endl;
}

利用迭代器遍历链表list

list<int> li{ 2, 4, 6, 8, 10 };
for(auto it = li.begin(); it != li.end(); ++it) {
    cout<<*it<<endl;
}

大家可以看到,上述两端代码唯一进行修改的就是将vector修改为list(vi修改成li仅仅是为了命名的区别),遍历代码没有任何改变,就可以轻易完成底层存储结构从数组到链表的转化,是不是特别棒?

例子2:一个算法的例子,将当前迭代器向前移动off个单位
算法原型:

advance函数:它接收一个迭代器参数,以及一个偏移量_Off,表示将当前的迭代器向前移动_Off个长度(当_Off<0的时候,相当于向后移动)
template<class _InIt, class _Diff> inline
void advance(_InIt& _Where, _Diff _Off)
{   // increment iterator by offset, arbitrary iterators
    _Advance(_Where, _Off, _Iter_cat(_Where));
}

利用advance函数将vector的迭代器it向前移动3个单位

auto it = vi.begin();  //vi = {1, 3, 5, 7, 9}
cout<<*it<<endl; //we get 1

advance(it, 3); 
cout<<*it<<endl; //we get 7

利用advance函数将list的迭代器it向前移动3个单位

auto it = li.begin();  //li = {2, 4, 6, 8, 10}
cout<<*it<<endl; //we get 2

advance(it, 3); 
cout<<*it<<endl; //we get 8

例子1和2形象的展示了迭代器处理的抽象一致性。不用关心底层容器的结构构建,而用一种统一的方式来对容器进行处理,而且在此基础上进一步实现通用一致的算法,岂不妙哉。当需要修改底层容器的结构时候,只需要修改容器的创建代码,其他算法层面基本不需要改动。

有没有感觉到它的美,那么很容易疑问它是如何实现不同容易的统一调用的呢?在回答这个问题之前,我想先简单说一下Java的实现方案(本人只根据个人想法来写,也许与实际的情况有一点点的偏差,不过本人可以担保,思想肯定是这样的,编程学的就是思想!)

Java的实现

首先盗取网上的一张图(本来是C#的,其实Java实现也是这个结构)
图片1-Java迭代器

Aggregate类可以认为是集合抽象类,Iterator是迭代器抽象类。迭代器抽象类包含几个抽象方法(可见名知意)。如果需要实现一个具体容器,首先需要实现抽象容器的方法,还需要实现一个具体迭代器类,它通过具体容器的CreateIterator()函数进行绑定。这样ConcreteIterator就持有了具体容器的this指针,就可以实现相对应的first,next等方法了。

例子3:以java中的数组ArrayList为例,代码来源于AB,原谅我未经同意就盗取了代码,只是为了分享知识。

首先实现具体的容器类ArrayList,它继承一个抽象容器接口Collection,大概形如

public class ArrayList implements Collection {
     
    Object[] objects = new Object[10];  
    int index = 0;  

    @Override  
    public void add(Object o) {  
        if(index == objects.length) {  
            Object[] newObjects = new Object[objects.length * 2];  
            System.arraycopy(objects, 0, newObjects, 0, objects.length);  
            objects = newObjects;  
        }  
        objects[index] = o;  
        index ++;  
    }  
    ...
 }

代码中只简单显示了add函数的实现。ArrayList首先内部创建了一个数据objects,当增加新的元素时,先判断数组是否已经满了,如果已满,那么重新分配一个长度*2的数组,将元素复制过去,然后将新增的元素放入到index指向的位置,并将index增加1。其实index就代表是数组中元素的个数。

然后实现它的迭代器类,ArrayList实现了一个内部类,ArrayListIterator,它继承于Iterator抽象接口,并实现相应的接口方法。示例代码如下:

private class 
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值