STL一:历史与组件速览

rel="File-List" href="file:///E:%5Ctmp%5CAPPLIC%7E1%5Cmsohtml1%5C05%5Cclip_filelist.xml"> rel="Edit-Time-Data" href="file:///E:%5Ctmp%5CAPPLIC%7E1%5Cmsohtml1%5C05%5Cclip_editdata.mso">

——STL的优点就不罗嗦了,对一个C++开发人员来讲,不熟悉STL是无论如何都说不过去的,这不需要什么借口。侯捷老师的大作《STL源码剖析》确实是深入学习STL的绝佳教材,于是决定好好研读一下这本书,并将所学记录于blog上,作为一个学习笔记,说不定还能遇到不少同道中人共同学习。

如果能更多的了解STL的机制,就可以不仅更加纯熟的应用,掌握一个开发的利器,更能学习其设计思想而加以应用,使自己的功力更进一层。

STL简简史

C++Bjarne Stroustrup创立于1979年,而就在那一年Alexander Stepanov创立了STL,大师的眼界总是这么超前哪;直到19939STL才开始了进入C++标准库的历程,并于19989STL终于正式进入C++标准,成为C++程式库的一大派系。就连C++程式库原有的streamstring也都用template重新写过,可见其影响力(经常看到网上对string的指责,应该和后入STL也有点关系吧)。

STL有不同的版本,包括HP的版本(所有STL之源),P.J.Plauger版本(Visual C++采用的就是这个),Rouge Wave版本(C++ Builder采用)和SGI版本。侯捷老师推荐的是SGI的版本,可读性更高,《STL源码剖析》也是以其为蓝本。

STL 六大组件

学习使用STL是相对简单的,然而如果要深入STL的底层,那里却是海底的冰山,其复杂性是不言而喻的,哦,希望不要把人吓倒,好消息是:这也是一座充满惊喜的宝库。

先来看看这六大组件吧,这里先有个基本的概念,等用到它们的时候再详细探究到底是怎么回事吧。

1. 容器(containers)STL里面有很多容器,比如list, vector, deque, ma

p,这都是比较常用的,容器是用来组织存放数据的。你甚至可以把int A[20]声明的数组看作是一个整型容器,它以线性相关的方式存储了20个整型数据。STL的容器是一种class template

2. 演算法(algorithms),比如sort, search等各种常用的算法,STL中的演算法相当于function template

3. 迭代器(iterators), 有了容器就需要知道如何访问容器里面的元素,就像一个数组可以使用索引访问一样,迭代器就是访问容器的接口,而又不会出卖容器内部的数据组织方式。所有的STL容器都必须附带自己的迭代器——毕竟只有容器设计者自己才知道如何访问容器的元素。

4. 仿函式(functors),防函式是一种重载了operator()class或者class template,容易让人感到困惑的东西。

5. 适配器(adapters),一种包装了容器或者防函式的东西,只是根据需要提供必须的接口,而不是把提供原来的所有接口,想想DesignPattern中的Adapter模式吧,是一样的了。比如STL中的queuestack虽然很像容器,但是实际上只是适配器,因为其底层完全重用了deque

6. 配置器(allocators),负责空间分配管理,在STL中配置器也是一个class。将配置器独立成一个组件的好处就是,你可以根据需要定制自己的配置器,这样既可以利用S

TL的便利性,又可以满足效率的要求。

1-1显示了六大组件之间的相互关系。

STL源码解析》中还讲了STL中的各种常数定义,并用小程序测试了各平台对C++的支持度,在1.81.9.1节。

 

1-1 六大组件之间的互动关系【直接截自《STL源码剖析》】

Container通过Allocator获得存储空间;Algorithm通过Iterator存取Container的内容;

Adaptor可以套接FunctorFunctor协助Algorithm完成不同的策略变化。

 

1.9节还讲到了C++一些容易令人困惑的语法,临时对象(在下面会有提及);静态整型常量(int, long, char, short等整型类型)在class内的直接初始化;STL的前闭后开区间(数据始于begin而终结于last-1位置)等,这里只重复一下防函式的一些内容。

Function call运算子(operator () )速写

函数调用算子(C++语法中的())也可以被重载,如果一个类重载了(),它就成了一个仿函式。

C语言中,如果需要就将一个函数作为参数传递,只能通过指针的方式,比如常用的qsort(函数:

int cmp(const void *a, const void*b){ … }

A a[20];

qsort(a, 20, sizeof(A), cmp);

 

而在STL中,这些是通过防函式完成的,防函式具有可适配性(adaptability)——也就是可以将某些条件加于其上而改变其状态,这是函数指针不具有的,和上面对应的例子如下:

template<class T>

class CCmp{

public: // 重载了(),类CCmp就成了一个防函式

       int operator()(const T &a, const T &b){ … }

};

// 声明防函式对象

CCmp<A> cmpA;

// 使用防函式就像使用函数一样

if(cmpA(a0, a1) < 0){

       cout<<”a0 < a1”<<endl;

}

// 还可以生成防函式的临时对象,同时使用

if(CCmp<A>()(a0, a1) < 0){

cout<<”a0 < a1”<<endl;

}

CCmp<T>已经很接近STL的防函式了,唯一缺乏的就是上面提到的可适配性。

 

今天暂时到这里吧,虽然磕磕绊绊也算可以成文了,明天继续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值