iterator,是stl中至关重要的一个组件,它是stl的基石,对于所有与容器有关的操作,几乎都用到iterator,本文先不谈iterator的各种使用技巧,而是谈谈iterator中的技术:
技术一:标记
//首先是迭代器的类型,我们需要一种方法来标记迭代器的类型,标记的方法多种多样,最简单的是使用掩码(宏定义)
//这里我们为什么不使用一个int或者unsigned来存储一个掩码,而是使用这些对象来表示呢?恰恰是因为节省了内存,因为这种对象
//的size是1个字节,所以我们需要对象时,仅仅是1个字节,而我们并不一定使用这个对象。为什么呢?首先我们明确这些类
//干什么用的,为了说明迭代器的类型。迭代器的类型信息经常会被使用吗?不经常,甚至可以说只是偶尔使用,那么我们如果使用
//掩码来表示类型,那么每个迭代器我们都需要至少2byte的数据来存储掩码,而我们需要为每个迭代器一个不常使用的特性浪费
//内存,这是不值得的。那么,使用下面的方法,效果如何呢?哈哈,对于iterator模板推断,其中使用typedef,size只有1byte,什么
//时候我们需要使用这个信息的时候,可是使用:动态识别。这个技术,在stl中没有涉及(mfc中有此技术);stl中使用了更巧妙的
//的方法,使用函数重载机制,利用此类型信息,具体的可参见使用与迭代器型别有关的算法
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 {};下面是iterator的基本定义:
template <class _Category, class _Tp, class _Distance = ptrdiff_t,
class _Pointer = _Tp*, class _Reference = _Tp&>
struct iterator {
typedef _Category iterator_category;
typedef _Tp value_type;
typedef _Distance difference_type;
typedef _Pointer pointer;
typedef _Reference reference;
};
技术二:特性的提取:
//我们对于迭代器的使用,需要迭代器的特性,这个技术非常重要。
//试想,我们得知到一个迭代器类型,我们如何知道这个迭代器所指向的数据类型?这个问题非常常见,必须解决。这里就需要
//特性提取技术,这种技术基于一种协议:所有的迭代器中都有一种value_type,代表所指的数据类型,此问题提供了这一类解决
//问题的方法,定义一种协议,大家都遵循,我们就可以解决很多看似很难的问题。mfc中的大部分技术都是采用这一解决方案
template <class _Iterator>
struct iterator_traits {
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
typedef typename _Iterator::difference_type difference_type;
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
//指针作为一种特殊的迭代器,我们需要特化,特化如下,值得注意,注意细节的处理:const 指针和一般指针两个特化版本
template <class _Tp>
struct iterator_traits<_Tp*> {
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef _Tp& reference;
};
template <class _Tp>
struct iterator_traits<const _Tp*> {
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef ptrdiff_t difference_type;
typedef const _Tp* pointer;
typedef const _Tp& reference;
};
//下面的技术用来提取迭代器的特性,为甚么这么做呢,直接使用_Iter::value_type不行吗?试想,如果迭代器是指针怎么办?
//很明显,我们需要迭代器对于指针的特化版本,
//首先想一下基于迭代器的算法的格式:template<class InputIter> function(InputIter __x)
//当我们__x是一个指针时,我们的InputIter被推断为指针,如何从指针中得出类型信息呢?指针并不是迭代器而是迭代器的一种特殊形式,
//两者的基本实现是不同的,但是都可以看做是迭代器,什么意思呢?就是说迭代器与指针是不同的两种东西,但是其性质是相似的
//我们需要一个包装,能涵盖这两个东西,而不是将指针实现为迭代器的特殊版本---这是不可能的。而这个包装就是大名鼎鼎的
//iterator_traits!
关于特性提取,类似的技术还有type_traits:
//这里采用与iterator一样的技术,标志用类来表示
struct __true_type {
};
struct __false_type {
};
template <class _Tp>
struct __type_traits {
typedef __true_type this_dummy_member_must_be_first;
typedef __false_type has_trivial_default_constructor;
typedef __false_type has_trivial_copy_constructor;
typedef __false_type has_trivial_assignment_operator;
typedef __false_type has_trivial_destructor;
typedef __false_type is_POD_type;
};说明一点:对于任意的类型,借助于type_traits,我们都有type_traits(即使是未定义)。所以最基本的type_traits是保证最低需求的:假设构造,复制等等都需要显示的操作。而对于确实不需要显示的复制,构造的类型,我们可以使用模板特化,例如:
template<> struct __type_traits<char*> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
本文探讨了C++ STL中迭代器的核心技术,包括标记和特性提取。通过详细解释不同类型的迭代器和它们的特性,文章揭示了如何在不常用的情况下节省内存,并介绍了如何高效地获取迭代器的相关信息。

被折叠的 条评论
为什么被折叠?



