SGISTL源码阅读五 迭代器上(迭代器的五种相应型别associated types)

SGISTL源码阅读五 迭代器上(迭代器的五种相应型别associated types)

前言

之前在对STL的简介中说到过,迭代器的作用是将数据结构(容器)和算法粘合在一起,我们可以将它理解成smart pointer,它是一种行为类似指针的对象。

什么是相应型别?

最初看到这个翻译觉得这个概念特别高大上,但是我们不要把它想得太复杂。
相应型别其实就是其字面意思,它可以指迭代器所指对象的类型,但是它又不止于此,常用的迭代器相应型别有五种,分别是

  • iterator_category
  • value_type
  • difference_type
  • pointer
  • reference

为什么要会存在相应型别?

我们知道迭代器的作用是将不同的数据结构和算法粘合在一起,如果仅仅只针对一种数据结构,那当然是很简单的了,原生指针都可以做到。迭代器使用相应型别,针对不同的类型使用不同的方式(通过模板偏特化实现),这样能大大提高地效率。

五种相应型别的详细介绍

iterator_category

根据移动特性与施行操作,迭代器被分为了五类,iterator_category区分了这五类迭代器。

  • Input Iterator
    这种迭代器所指的对象不允许外界改变(Read Only)
  • Output Iterator
    与上一个迭代器类似,这个迭代器所指的对象,Write Only
  • Forward Iterator
    这种迭代器允许在其所形成的区间上进行读写操作,但是只能向前(operator++)
  • Bidirectional Iterator
    同样可以进行读写操作,并且可以双向移动(operator++,operator–)
  • Random Access Iterator
    第五种类型涵盖了之前所有指针的算术能力(相加,相减,通过下标访问等)

他们的从属关系为:

在这里插入图片描述

value_type

这就是迭代器所指对象的类型。(类型==型别,但是更通俗一些)

difference_type

difference_type用来表示两个迭代器之间的距离,也可以用来表示一个容器的最大容量(因为对于连续空间的容器而言,头尾之间的距离就是其最大容量)。

pointer

这里的pointer型别其实就是指针。

reference_type

其实也很好理解,用我们最初在学习函数的时候的一个经典样例来说,交换a、b的值,其实就是传值和传引用的区别,这里的reference_type就是引用。按照是否能改变迭代器所指之物来分,迭代器可以分为两种:
1.constant iterators,不允许改变所指对象内容;
例如带有const修饰符的,就不能被改变
2.mutable iterators,允许改变所指对象内容。


深入源码

//从这里我们可以看到不同类型迭代器之间 的继承关系
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

template <class T, class Distance> struct input_iterator {
  typedef input_iterator_tag iterator_category;
  typedef T                  value_type;
  typedef Distance           difference_type;
  typedef T*                 pointer;
  typedef T&                 reference;
};

struct output_iterator {
  typedef output_iterator_tag iterator_category;
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;
};

template <class T, class Distance> struct forward_iterator {
  typedef forward_iterator_tag iterator_category;
  typedef T                    value_type;
  typedef Distance             difference_type;
  typedef T*                   pointer;
  typedef T&                   reference;
};


template <class T, class Distance> struct bidirectional_iterator {
  typedef bidirectional_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef Distance                   difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

template <class T, class Distance> struct random_access_iterator {
  typedef random_access_iterator_tag iterator_category;
  typedef T                          value_type;
  typedef Distance                   difference_type;
  typedef T*                         pointer;
  typedef T&                         reference;
};

在进行了一些分析之后再看源码其实很好懂了,根据迭代器的五种类型创建了5个相应的结构体,他们都是统一地,拥有五种相应型别。

参数推导机制

大家应该比较熟悉sizeof()吧,我们可以调用它来获取变量的长度,但是至于变量的类型呢?C++并未支持typeof(),但是可以使用 参数推导机制 ,一旦函数被调用,编译器会自动进行template参数推导。

总结

以上简要介绍了迭代器的五种相应型别和迭代器的类型
但是并非任何情况下任何一种相应型别都可以利用上述的template参数推导机制来取得的。
后面我们将介绍到traits编程技法。

猜你喜欢

转载自blog.csdn.net/lyn_00/article/details/83962132