C++ Primer 学习笔记_46_STL剖析(一):泛型程序设计、什么是STL、STL六大组件及其关系

一、泛型程序设计

1、泛型编程(generic programming):相同的逻辑和算法,对不同类型的数据进行处理
2、将程序写得尽可能通用
3、将算法从数据结构中抽象出来,成为通用的
4、C++的模板为泛型程序设计奠定了关键的基础



二、什么是STL

1、STL(Standard Template Library),即标准模板库,是一个高效的C++程序库。
2、包含了诸多在计算机科学领域里常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性

3、从逻辑层次来看,在STL中体现了泛型化程序设计的思想(generic programming)

(1)在这种思想里,大部分基本算法被抽象,被泛化,独立于与之对应的数据结构,用于以相同或相近的方式处理各种不同情形

4、从实现层次看,整个STL是以一种类型参数化(type parameterized)的方式实现的

(1)基于模板(template)

(2)模板,泛型程序设计思想,STL的关系

模板为泛型程序设计奠定了基础

STL是一套C++标准模板库,体现了泛型程序设计思想,换句话说,STL是泛型程序设计思想比较成功的一套产品



三、STL六大组件及其关系

1、STL六大组件

————Container(容器) 各种基本数据结构

————Adapter(适配器) 可改变containers、Iterators或Function object接口的一种组件(之前通过deque是实现了新的容器Stack,Stack称为容器适配器)

————Algorithm(算法) 各种基本算法如sort、search…等

————Iterator(迭代器) 连接containers和algorithms,迭代器是容器与算法的桥梁

————Function object(函数对象) 

————Allocator(分配器)



2、容器算法迭代器关系

容器是数据结构,算法是逻辑,迭代器是遍历接口

C++ Primer 学习笔记_46_STL剖析(一):泛型程序设计、什么是STL、STL六大组件及其关系_第1张图片


3、容器

(1)容器类是容纳、包含一组元素或元素集合的对象


(2)七种基本容器:

————向量(vector)、双端队列(deque)、列表(list)、集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap)


(3)标准容器的成员绝大部分都具有共同的名称

C++ Primer 学习笔记_46_STL剖析(一):泛型程序设计、什么是STL、STL六大组件及其关系_第2张图片


(4)序列式容器

————序列式容器Sequence containers,其中每个元素均有固定位置——取决于插入时机和地点和元素值无关。(vector、deque、list)


(5)关联式容器

————关联式容器Associative containers,元素位置取决于特定的排序准则以及元素值和插入次序无关。(set、multiset、map、multimap)


(6)如何选择序列式容器

【1】、需要频繁在序列中间位置上进行插入和/或删除操作不需要过多地在序列内部进行长距离跳转,应该选择list。不支持下标操作

【2】、vector头部与中间插入删除效率较低,在尾部插入与删除效率高支持下标操作

【3】、deque是在头部与尾部插入与删除效率较高。支持下标操作



4、迭代器

(1)迭代器Iterators,用来在一个对象群集(collection of objects)的元素上进行遍历。这个对象群集或许是个容器,或许是容器的一部分。迭代器的主要好处是,为所有容器提供了一组很小的公共接口。迭代器以++进行累进,以*进行提领,因而它类似于指针,我们可以把它视为一种smart pointer
(2)比如++操作可以遍历至群集内的下一个元素至于如何做到取决于容器内部的数据组织形式
(3)每种容器都提供了自己的迭代器,而这些迭代器能够了解容器内部的数据结构


5、算法

    算法Algorithms,用来处理群集内的元素。它们可以出于不同的目的而搜寻、排序、修改、使用那些元素。通过迭代器的协助,我们可以只需编写一次算法,就可以将它应用于任意容器,这是因为所有的容器迭代器都提供一致的接口

6、适配器

(1)、适配器一种接口类构造出新的类

【1】为已有的类提供新的接口 stack、queue

【2】目的简化、约束、使之安全、隐藏或者改变被修改类提供的服务集合

(2)、三种类型的适配器

【1】容器适配器:用来扩展7种基本容器,它们和顺序容器相结合构成栈、队列和优先队列容器

【2】迭代器适配器(反向迭代器、插入迭代器、IO流迭代器)

【3】函数适配器(函数对象适配器、成员函数适配器、普通函数适配器)


7、函数对象

(1)、函数对象(function object)也称为仿函数(functor)
(2)、一个行为类似函数的对象,它可以没有参数,也可以带有若干参数。
(3)、任何重载了调用运算符operator()的类的对象都满足函数对象的特征
(4)、函数对象可以把它称之为smart function。
(5)、STL中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类。为了调用这些标准函数对象,需要包含头文件<functional>。


8、分配器

负责空间配置与管理。从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的class template

隐藏在这些容器后的内存管理工作是通过STL提供的一个默认的allocator实现的。当然,用户也可以定制自己的allocator,只要实现allocator模板所定义的接口方法即可,然后通过将自定义的allocator作为模板参数传递给STL容器,创建一个使用自定义allocator的STL容器对象,如:
    stl::vector<int, UserDefinedAllocator> array;
    大多数情况下,STL默认的allocator就已经足够了。这个allocator是一个由两级分配器构成的内存管理器,当申请的内存大小大于128byte时,就启动第一级分配器通过malloc直接向系统的堆空间分配,如果申请的内存大小小于128byte时,就启动第二级分配器,从一个预先分配好的内存池中取一块内存交付给用户,这个内存池由16个不同大小(8的倍数,8~128byte)的空闲列表组成,allocator会根据申请内存的大小(将这个大小round up成8的倍数)从对应的空闲块列表取表头块给用户。

这种做法有两个优点:
   (1)小对象的快速分配。小对象是从内存池分配的,这个内存池是系统调用一次malloc分配一块足够大的区域给程序备用,当内存池耗尽时再向系统申请一块新的区域,整个过程类似于批发和零售,起先是由allocator向总经商批发一定量的货物,然后零售给用户,与每次都总经商要一个货物再零售给用户的过程相比,显然是快捷了。当然,这里的一个问题时,内存池会带来一些内存的浪费,比如当只需分配一个小对象时,为了这个小对象可能要申请一大块的内存池,但这个浪费还是值得的,况且这种情况在实际应用中也并不多见。
   (2)避免了内存碎片的生成。程序中的小对象的分配极易造成内存碎片,给操作系统的内存管理带来了很大压力,系统中碎片的增多不但会影响内存分配的速度,而且会极大地降低内存的利用率。以内存池组织小对象的内存,从系统的角度看,只是一大块内存池,看不到小对象内存的分配和释放。




参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范

你可能感兴趣的:(C++,泛型,STL)