STL表现的如此出色的,迭代器(iterator)做出了很大的贡献,功不可没。
一个数据元有多重表示方式,包括:实体(它自己),指针,引用;另外,还有两个与数据元属性相关的类型:间距(即两个数据元之间的关系)和其移动特性与施行方式的类型。迭代器中包含了这上述五种与数据元先关的描述,所以迭代器能够很充分的表示和操控一个数据元。迭代器本身只能表示操作数据元,但是它没有含括任何的数据元数据,就似电视机和遥控器之间的关系,遥控器(迭代器)只是能够切换不同的频道,但是它不含括电视机(数据元)。
这里不单独描述迭代器,它个单不是一独的个体,放在其所属的大框架中,更能体现它的作用和执行机制。
STL中会定义迭代器:
template <class _Ty> /*_Ty:节点元素类型。*/
struct container_iterator
{
/*五种与数据元先关的描述。*/
......
typedef container_iterator<_Ty> iterator;
typedef bidirectional_iterator_tag itetator_category;
typedef _Ty value_type;
typedef Node<_Ty>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
link_type node;
/*迭代器构造函数。*/
......
container_iterator(link_type x):node(x){}
...
......
/*迭代器行为*/
/*+,-,++,--,+=,-=,->,&,[]等运算符重载各取所需 */
};
从中看出,迭代器不包含数据实体,它只是能表现和操作数据实体。因为上述container_iterator操控的的实现,因此当手头有一container_iterator的时候,你可以“*ite”来获得数据元的引用,可以“ite->”获得数据元的指针,“++”可以另ite自动前进一步,“–”可以另ite后退一步。。。
通过模板,迭代器可以为任何数据元服务。一个有趣的地方便是迭代器的构造函数:
container_iterator(link_type x):node(x){}
在container(以下展示)的元素操作当中,很多时候会直截返回指向数据元的指针,这时可能此操作的函数可能需要返回的是container_iterator类型,而不是返回一个指向数据元的指针(这种做法不上道,太龌龊),于是会临时构造(调用迭代器的构造函数)一个迭代器作为返回值。
意即:
class Node
{
public:
Node(int nAge = 0)
{
m_nAge = nAge;
}
......
private:
int m_nAge;
};
Node foo(int i)
{
return i; /*直截返回一个int,但Node有Node(int)构造函数,因此会临时构造一个Node对象返回。*/
}
int main()
{
Node i = foo(2);
return 0;
}
下面是container:
template <class _Ty,class alloc> /*T:节点元素类型。*/
class container
{
/*container数据结构*/
typedef container_iterator<_Ty> iterator;
typedef const container_iterator<_Ty> const_iterator;
typedef Node<_Ty>* link_type;
typedef _Ty value_type;
typedef Node<_Ty>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
private:
link_type head; /*头指针。*/
link_type tail; /*为指针。*/
iterator begin();
iterator end();
bool empty();
size_type size()const ;
......
/*元素的操作。push_front,push_back,pop_front,pop_back,insert,earse等根据容器的不同各取所需。*/
iterator insert(const _Ty& x);
iterator earse(iterator position);
void push_back(const _Ty& x);
void push_front(const _Ty& x);
void pop_back();
void pop_front();
......
};
container内部实现的大多数是元素的操作函数,它们有充分利用container_iterator,包括container_iterator内部实现的各种元素的操控(++,–,*,->等等)。
container和container_iterator就是这样结合起来的。还剩下一STL中的镇库之宝:算法。通用的的算法中,少不了迭代器。如何能做到通用?不同的容器对应不同的迭代器,那是否对于一个算法,要实现多个迭代器的版本?不,不需要,这就是泛化编程的好处,根据传入的迭代器(一般的STL算法会以迭代器作为参数)来推导出相应的迭代器类型。以最为简单的find()算法为例:会通过_InIt _First来推导出迭代器的类型,推导出迭代器的类型,也就推导出了相应的容器。
/*摘自c++ standard library。*/
template<class _InIt, class _Ty>
inline
_InIt find(_InIt _First, _InIt _Last, const _Ty& _Val)
{ // find first matching _Val
_ASSIGN_FROM_BASE(_First,
_Find(_CHECKED_BASE(_First), _CHECKED_BASE(_Last), _Val));
return (_First);
}
template<class _InIt, class _Ty>
inline
_InIt _Find(_InIt _First, _InIt _Last, const _Ty& _Val)
{ // find first matching _Val
_DEBUG_RANGE(_First, _Last);
for (; _First != _Last; ++_First)
if (*_First == _Val)
break;
return (_First);
}
我们看到,迭代器在算法中的表现,++,–,==。。。。
故迭代器和算法模块结合了。STL中迭代器,容器,算法三足鼎立,整体上通力合作,细微之处不乏各司其职。妙哉!妙哉!
本文完 2012-10-28
Dylan http://daoluan.github.io/
28 October 2012 会持续更新