迭代器学习笔记

本文是学习《STL源码剖析》时的学习笔记。

1、迭代器是一种smart pointer

迭代器是一种类,其包装了原生指针,并重载了operator*、operator->、operator!=、operator++等等,因此其行为类似指针。
容器为了储存各种类型的元素,定义为类模板。与此相似,为了使迭代器能够指向不同类型的容器元素,迭代器也需要定义为类模板。
不同的容器遍历方法不同,在重载operator++时,必须根据不同的容器确定。因此,实现迭代器时需要对容器的实现细节有非常丰富的了解。所以容器的设计者需要实现其相应的迭代器。这正是为什么每一种STL容器都提供了专属迭代器的缘故。

2、迭代器相应型别(associated type)

迭代器相应型别就是迭代器相关的一些类型信息。常用的迭代器型别有五种:value type、difference type、reference type、pointer type、iterator category;
value type:指迭代器所指对象的类型。
difference type
reference type:如果函数要传回左值,则返回值类型必须是引用。T&和const T&就是两种不同的引用类型。
pointer type:顾名思义
iterator category
如果希望自己开发的容器能与STL很好地结合使用,必须为你的容器迭代器定义这五种相应型别。

2.1为什么需要迭代器相应型别?

STL通过迭代器的使用将数据容器和算法分离开来。算法使用迭代器而不是容器作为输入。在算法中运用迭代器时,很可能会遇到其相应型别!
例如:一个函数以迭代器为输入,在函数体内部需要定义以“迭代器所指对象的类型”为类型的临时变量,这个时候就用到了value type。再例如,一个函数以迭代器为输入,需要返回迭代器所指对象的引用,这时候函数返回值类型就用到了reference type。

2.2 如何定义迭代器相应型别?

现在我们知道了迭代器相应型别很有用,那么该如何定义它呢?
使用内嵌型别声明是个不错的解决方案,看下面的例子。

    template<class T>
    struct MyIter{
    typedef T value_type //内嵌型别声明(nested type)
    typedef T& reference_type
    T* ptr;
    ...
    }

在迭代器MyIter中声明了value_type和reference_type,注意,它们只是在类作用域中可见。

    template<typename I>
    typename I::value_type //这一行是函数的返回值,typename表明后面是一个类型名而不是变量
    func1(I ite)
    {return *ite;}

    template<typename I>
    typename I::reference_type //这一行是函数的返回值,typename表明后面是一个类型名而不是变量
    func2(I ite)
    {return *ite;}

上面func1返回迭代器所指对象的值,func2返回迭代器所指对象的引用。看上去这两个函数可以处理任意的迭代器(只要它声明了相应型别)。但现在出现了一个新的问题:并不是所有的迭代器都是类类型。比如说原生指针就不是,那么就无法为它定义内嵌型别!

3 Traits编程技法

为了解决上面的问题,我们需要加一个“间接层”。

具体做法是编写一个类模板,专门用来“萃取”迭代器的特性(相应型别)。

也就是说,使用一个模板类来提取迭代器相应型别。
也就是说可以像下面这样:

    template<class I>
    struct iterator_traits{
    typedef typename I::value_type value_type;//其实这里还是没有解决原生指针的问题
    }

这个所谓的traits,其意义是,如果I定义有自己的value_type,那么通过这个traits的作用,萃取出来的value_type就是I::value_type。

原来的func1函数可以如下定义:

    template<typename I>
    typename iterator_traits<I>::value_type //这一行是函数的返回值
    func1(I ite)
    {return *ite;}

这里的iterator_traits还是没有解决原生指针的问题。但是我们可以(必须)为原生指针T*和const T*编写一个iterator_traits特例版本,相关技术参考template partial specialization,C++primer16.5小节 模板特例化。

template<class T>
struct iterator_traits<T*>{
typedef T value_type;
}

template<class T>
struct iterator_traits<const T*>{
typedef T value_type;
}

至此我们成功地解决了获取原生指针的相应型别的问题!
再次提醒,iterator_traits必须针对传入的型别为pointer或者point-to-const设计特化版本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值