《Essential C++》泛型编程

前言

Standard Template Library(STL)主要由两部分组件构成:一个是容器(container),包括vector、list、set、map等类,另一种组件是用以操作这些容器类的所谓泛型算法(generic algotithm),包括find(),sort(),replace(),merge()等等

vector和list这两种容器室所谓的序列式容器(sequentialcontainer),序列式容器会依次维护第一个元素、第二个元素……直到最后一个元素。我们在序列式容器上主要进行所谓的迭代(iterate)操作,map和set这两种容器属于关联式容器,关联式容器可以让我们快速寻找容器中的元素值。

所谓map是一对对的key/value组合,key用户搜寻,value用来表示我们要存储或取出的数据。例如,电话号码可以轻易用map表示,电话用户名便是key,而value与电话号码产生关联。

所谓set,其中仅含有key,我们队它进行查询操作,为的是要判断某值是否在于其中,如果我们想要建立一组索引表,用来记录新闻,故事中出现的子,我们可能会希望将一些中性字眼,比如the、an、but排除掉,在放行某个字,让它进入索引表前,我们先查询excluded_word这么一个set,如果这个字存在其中,我们便忽略它,不再计较,反之则将此字加入索引表。

所谓泛型算法,提供了许多可施行于容器类及数组型别上的操作行为,这些算法之所以被称为泛型(generic),因为它们和它们想要操作的元素型别无关,比如int,double或string无关,它们同样也和容器型别彼此独立,无论是vector、list或array。

泛型算法通过function template技术,达成“与操作对象之型别相互独立”的目的。而达成“与容器无关”的诀窍,就是不要直接在容器身上进行操作,取代方式是,藉由一堆iterators (first, last)、表示我们欲进行迭代的元素区间。如果first等于last,算法便只作用于first元素,如果first不等于last,算法便会首先作用于first所指元素身上,并将first前进一个位置,然后再作用于当前的first所指元素身上,如此持续进行,知道first等于last位置。

泛型指针 Iterators

我们需要设计一组iterator classes,让我们可以使用和指针相同个的语法来进行程序的撰写。举个例子,如果first和last都是list的iterators,我们可以这样写

while (first!=last)
{
       cout<< *first << ‘ ’;
       ++first;
}
 

这就像吧first和last当做指针一样,唯一的区别在于其dereference, !=, ++是由iterators classes 内相关的inline函数提供的。

 

如何取得iterators?

每个标准容器都提供一个名为begin()的操作函数,可返回一个iterator,指向第一个元素;另一个end()的操作函会返回一个iterator,指向最后一个元素的下一个位置。以下是对iterator进行assign, compare,increment, dereference操作:

for (iter = svec.begin()); iter != svec.end();++iter)
         cout<< *iter << ‘ ’;

哪些信息是这份定义应该提供的:

(1)    迭代对象(某个容器)的类别,这可以用来决定如何存取下一个元素

(2)    iterator所指的数据型别,这可以决定iterator提领操作的返回值

 

iterator的一种可能的定义形式,便是将上述的两个型别作为参数,传给iterator class:


//iterator的一种可能的定义形式

//这不是STL的做法

iterator <vector, string> iter;

 

实际语法看起来复杂一些,并提供更优雅的解法,虽然后者可能并不十分明显,但是当我们实现并运用iterator class后,会有所体会。

 

vector<string> svec;

//以下是标准程序库中的iterator语法

//iter指向一个vector,后者的元素型别为string

//iter一开始指向svec的第一个元素

vector<string>::iterator iter =svec.begin();

此处的iter被定义为一个iterator,指向一个vector,后者的元素型别为string,其初值指向svec的第一个元素,式中的::表示此iterator是位于string vector定义式内的嵌套(nested)型别。

对于const vector:

const vector<string> cs_vec;

我们使用const_iterator来进行遍历操作:

vector<string>::const_iterator iter =cs_vec.begin();

const_iterator允许我们读取vector的元素,但是不允许任何写入操作。


vector<elemType>::const_iteratoriter = vec.begin();

vector<elemType>::const_iteratorend_ti = vec.end();

 

display()函数重新翻修后的面貌

template <typename elemType>

void display(constvector<elemType> & vec, ostream & os)

{

vector<elemType>::const_iteratoriter = vec.begin();

vector<elemType>::const_iteratorend_ti = vec.end();

      

       for(; iter != end_it; ++iter)

              os<< *iter << ‘ ’;

       os<< endl;

 

}

 

重新设计find(),让它同时支持两种形式:一对指针或者是一对iterators

 

template <typename IteratorType,typename elemType>

IteratorType

find(IteratorType first, IteratorTypelast, const elemType &value)

{

       for( ; first != last; ++first)

              if(value == *first)

                     returnfirst;

       returnlast;

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值