windows编程技术21STL泛型编程Word文件下载.docx
- 文档编号:16390167
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:73
- 大小:335.61KB
windows编程技术21STL泛型编程Word文件下载.docx
《windows编程技术21STL泛型编程Word文件下载.docx》由会员分享,可在线阅读,更多相关《windows编程技术21STL泛型编程Word文件下载.docx(73页珍藏版)》请在冰豆网上搜索。
光有模版是远远不够的,还需要能够表示这种集合的容器、能够在容器中遍历的迭代器、能够为算法和容器实现抽象存储的分配器、能够在不同容器之间进行转换的适配器、以及针对容器中数据集合的各种与具体类型无关的通用算法等。
这些正是泛型编程的研究内容,也是STL要实现的目标。
21.1.2泛型编程与STL
泛型编程是一种面向算法的多态技术,STL是它的一种具体实现。
1.泛型编程
在计算机科学中,泛型(generic,类属)是一种允许一个值取不同数据类型(所谓多态)的技术,强调使用这种技术的编程风格被称为泛型编程。
泛型编程研究对软件组件的系统化组织,目标是推出一种针对算法、数据结构和内存分配机制的分类方法,以及其他能够带来高度可重用性、模块化和可用性的软件工具。
与针对问题和数据的面向对象的方法不同,泛型编程中强调的是算法。
是一类通用的参数化算法,它们对各种数据类型和各种数据结构都能以相同的方式进行工作,从而实现源代码级的软件重用。
例如,不管(容器)是数组、队列、链表、还是堆栈,不管里面的元素(类型)是字符、整数、浮点数、还是对象,都可以使用同样的(迭代器)方法来遍历容器内的所有元素、获取指定元素的值、添加或删除元素,从而实现排序、检索、复制、合并等各种操作和算法。
泛型编程的通用化算法,是建立在各种抽象化基础之上的:
利用参数化模版来达到数据类型的抽象化、利用容器和迭代器来达到数据结构的抽象化、利用分配器和适配器来达到存储分配和转换接口的抽象化。
2.STL
STL(StandardTemplateLibrary,标准模板库)是泛型编程思想的实际体现和具体实现,它是一种为泛型组件建立大型标准库的可扩展架构。
STL本身,与面向对象无关,也与具体的程序设计语言无关。
STL的目标是,在不损失效率的基础上,进行抽象。
这里的不损失效率,是指尽最大努力来保证其所有的泛型算法是最优的,并且和手工为具体类型编写的代码具有同样的运行效率。
抽象的基础是数学逻辑和冯·
诺依曼计算模型(存储程序体系结构)。
如果用数学语言来描述,STL的本质就是:
不同的数据结构,对应于不同的地址代数结构、以及不同的地址连接方式。
从数据结构的一个地址,转向下一个地址的一些列操作,就对应于迭代器。
在数据结构中添加和删除地址的操作,就对应于容器。
STL将容器看作是结构的泛化,它们都拥有成员,可以描述整体和局部这一现实世界事物的关键属性。
STL使用了赋值的算法,要求采用面向值的语义。
STL还假定对容器中的数据和对象,定义了全序。
STL的主要内容是容器、泛型算法、迭代器、函数对象、分配器和适配器等6种组件。
在标准C++中,STL是作为C++标准库的一部分而出现的。
作为STL的基础的模板,则是C++语法的一部分。
3.历史
泛型程序最早出现1970年代的CLU和Ada语言中,后来被许多基于对象和面向对象的语言所采用,包括BETA、C++、D和Eiffel等。
1993年C++在3.0版中引入的模版技术就属于泛型编程的范畴,1994年7月ANSI/ISOC++标准委员会通过的STL,更是泛型编程的集大成者,它已被纳入1998年9月推出的C++国际标准之中。
VisualC++从2005版开始,全面支持C++的1998年和2003年国际标准,当然也包括STL泛型编程。
Java于2004年9月在JavaSE5.0(JDK1.5)中开始使用泛型技术,并且因此将从JDK1.2~1.4一直使用的Java2改名为Java5,但是为了在语法、类库和字节码上与传统的Java2兼容,Java中的泛型做出了很多牺牲,包括类型信息被擦除。
所以Java中的泛型是一种受限的非完整泛型。
微软于2005年11月在.NET框架2.0版、C#2.0和VisualBasic2005中也于引入了泛型编程,并在2007年11月推出的.NET框架3.5版中又增加了对STL的支持。
DavidMusserAlexanderStepanov
1971年,美国计算机科学家DavidMusser首先提出并推广了泛型编程的理论,但是主要局限于软件开发和计算机代数领域。
1979年,苏联籍的美国计算机科学家AlexanderStepanov开始研究泛型编程,1987年他与DavidMusser一道,开发出Ada的泛型表处理库。
1990年前后,Stepanov先后在贝尔实验室和HP实验室,进行泛型编程的研究和库设计,提出了STL的体系结构。
1993年11月,受贝尔实验室的AndrewKoening的邀请,Stepanov在ANSI/ISOC++标准委员会的会议上,介绍了泛型编程的理论和他们的工作。
Stepanov和MengLee按委员会的要求,于1994年3月提出了STL的草案。
委员会提出了一些修改意见,其中最重要的是对关联容器的扩充,由Musser完成了扩充部分的实现工作。
1994年7月,ANSI/ISOC++标准委员会终于通过了修改后的STL方案,并将其纳入1998年推出的C++标准之中。
1994年8月,HP将Stepanov和Lee等人开发的STL,在因特网上免费发布。
1995年Stepanov又到SGI工作,他与HansBoehm和MatthewH.Austern一起,为SGI开发了STL。
SGI也把它免费地放在了因特网上(
鉴于AlexanderStepanov对STL的重大贡献,他被誉为STL之父。
21.2容器
容器(container)是装有其他对象的对象。
容器里面的对象必须是同一类型,该类型必须是可拷贝构造和可赋值的,包括内置的基本数据类型和带有公用拷贝构造函数和赋值操作符的类。
典型的容器有队列、链表和向量等。
在标准C++中,容器一般用模版类来表示。
不过STL不是面向对象的技术,不强调类的层次结构,而是以效率和实用作为追求的目标。
所以在STL并没有一个通用的容器类,各种具体的容器也没有统一的基类。
容器可以视为是数组的推广,即对象的数组(广义数组),其中的元素(对象)可以用下标(索引)来访问。
容器的设计有两条准则:
一是在各个容器的设计中,提供尽可能大的自由度;
二是使各种容器能够向用户呈现出一个公共的界面/接口。
目的是,使容器的实现能达到最佳效率,同时也使用户能写出不依赖于所使用的特定容器类型的通用代码。
容器的设计通常只能满足这两条中的一条,但是STL却提供了一个同时具有通用性和执行效率的解决方案。
21.2.1分类
标准C++的STL框架中的主要容器有序列容器和关联容器两大类,另外两大类容器分别是容器适配器和拟容器。
1.序列容器
序列容器(sequencecontainer,顺序容器)将一组具有相同类型T的对象,以严格的线性形式组织在一起。
序列容器可以视为数组和链表的推广。
STL中的序列容器有如下3种:
1)vector<
T>
(向量)——提供对变长序列的快速随机访问(即对第i个元素的访问时间,是与i无关的常量),对序列末尾的插入和删除操作的时间是分摊常量;
(似变长数组)(对应于vector类,定义在<
vector>
头文件中)。
2)deque<
(double-endedqueue,双端队列)——提供对变长序列的快速随机访问,对序列头尾的插入和删除操作的时间都是分摊常量;
(似双向变长数组)(对应于deque类,定义在<
deque>
3)list<
(表)——提供对变长序列的线性时间访问(O(N),N为序列的当前长度),但是在序列的任意位置的插入和删除操作均为常量时间。
(似双向链表)(对应于list类,定义在<
list>
2.关联容器
关联容器(associativecontainer,联合容器)的特点是(键)有序的,即元素是按预定义的键顺序(如升序)插入的。
关联容器具有从基于键的集合中快速提取对象的能力,其中集合的大小在运行时是可变的。
关联容器可以视为关联数组、映射或字典的推广,它们保存的都是值的对偶,给定了其中的一个被称为键(key)的值,就可以快速访问与其对偶的另一个被称为映射值(mappedvalue)的值。
STL中的关联容器有如下4种:
1)set<
Key>
(集合)——支持唯一键值,并提供对键本身的快速检索;
例如set<
long>
:
{学号}。
集合关联容器,对应于set类,定义在<
set>
头文件中。
2)multiset<
(多重集合)——支持可重复键值,并提供对键本身的快速检索;
string>
{姓名}(可能有同名的)。
多重集合关联容器,对应于multiset类,也定义在<
3)map<
Key,T>
(映射/映像)——支持唯一Key类型的键值,并提供对另一个基于键的类型T的快速检索;
例如map<
long,string>
{(学号,姓名)}、{(电话号码,姓名)}等。
映射关联容器,对应于map类,定义在<
map>
4)multimap<
(多重映射)——支持可重复Key类型的键值,并提供对另一个基于键的类型T的快速检索;
string,string>
{(姓名,地址)}、{(姓名,年龄)}等。
多重映射关联容器,对应于multimap类,也定义在<
为了改进搜索的时间,微软还在STL的VC实现中,增加了4种对应的散列(hash)关联容器类型:
1)hash_set<
Key,H>
(散列集),对应于hash_set类,定义在<
hash_set>
2)hash_multiset<
(散列多集),对应于hash_multiset类,也定义在<
3)hash_map<
Key,T,H>
(散列映射),对应于hash_map类,定义在<
hash_map>
4)hash_multimap<
(散列多映射),对应于hash_multimap类,也定义在<
3.容器适配器
容器适配器(containeradapter)不是独立的容器,只是某种容器的变种,它提供原容器的一个专用的受限接口。
特别是,容器适配器不提供迭代器。
在STL中有如下3种容器适配器:
1)stack<
(栈)——只支持top()(读取栈顶元素)、push()(在栈顶处加入新元素)和pop()(取出栈顶元素)操作(先入后出)的一种序列容器。
可以是对任意一种序列容器(默认为双端队列deque)的限制实现:
删除非栈操作,将原来序列容器的标准操作back()、push_back()和pop_back()重新命名为top()、push()和pop()。
栈容器适配器,对应于stack类,定义在<
stack>
2)queue<
(队列)——与stack类似,queue也是对序列容器(默认也为双端队列deque)的限制实现。
与栈相比,队列也支持back()(读取队尾处的元素)和push_back()(在队尾处插入新元素)操作,但是不再支持pop_back()(取出队尾处的元素)操作。
不过,队列却允许front()(读取队首处的元素)和pop_front()(取出队首处的元素)操作(前出后入)。
由于矢量vector容器不支持pop_front()操作,所以不能作为队列queue的基础容器。
与前后都可出入的双端队列deque相比,队列queue缺少push_front()和pop_back()操作。
队列容器适配器,对应于queue类,定义在<
queue>
3)priority_queue<
(优先队列)——也是一种队列queue,不过其中的每个元素都被给定了一个优先级,用来控制元素到达队首top()的顺序。
默认情况下,优先队列简单地使用运算符<
进行元素比较,top()返回最大的元素。
注意,优先队列,并不要求其全部元素都是有序的,而只要求其第一个元素是最大的。
优先队列容器适配器,对应于priority_queue类,也定义在<
4.拟容器
拟容器(almostcontainer,似容器)在许多情况下可视为容器,但是又缺乏标准容器接口的某些方面和特性,不能与开发完全的容器进行全面互换。
除了内置数组外,STL中的拟容器有如下三3种:
1)string(串)——是实例化模版类basic_string<
char>
的类型定义typedef(另一个常用的wstring类,则是实例化模版类basic_string<
wchar_t>
的类型定义typedef)。
基本串basic_string提供下标操作、随机访问迭代器和其他序列容器的几乎所有功能,但是它不像容器那样支持广泛的元素类型选择,而且它还为作为字符串使用进行了优化,所以其典型使用方式与容器有着显著差异。
串拟容器,对应于string类,定义在<
有关string和wstring类的更详细内容,会在后面的21.6节中介绍。
2)valarray<
(值数组)——是为数值计算而进行了优化的向量,并不是一个具有通用性的容器。
valarray提供了许多有用的数值运算和常用的数学函数,但是它只提供了标准容器操作中的size()和下标操作,此外,其中元素的指针是一种随机迭代器。
值数组拟容器,对应于valarray类,定义在<
valarray>
3)bitset<
N>
(位集)——是标志位字段的扩展,它通过提供在N个二进制位的集合(下标0~N-1)上的各种操作,使对标志位的运算更为方便。
bitset可视为一个N位的二进制数,位取值0/1代表真假或开关,每一位从低位向高位进行编号。
位集拟容器,对应于bitset类,定义在<
bitset>
5.总结比较
我们将STL的各种容器及其性能罗列于表21-1中。
表21-1STL容器
类型
容器
访问方式
添加元素
删除元素
说明
序列
向量vector<
随机
尾
似变长数组
双端队列deque<
头尾
似双向变长数组
表list<
线形
任意位置
似双向链表
关联
集合set<
K>
顺序
移复
唯一健
多重集合multiset<
可多健
映射map<
K,T>
多重映射multimap<
适配器
栈stack<
尾(栈顶)
默认基deque
队列queue<
头
优先队列priority_queue<
头部的值最大
拟容器
内置数组a<
[N]
不能
只支持内置
基本数据类型
串string和wstring
是basic_string<
对char和wchar_t
类型的实例化
值数组valarray<
适合数值计算
位集bitset<
N个bool标志位
其中,“移复”是指,通过对被删元素后面的元素进行前移复制,来完成删除操作。
由于篇幅的限制,不能对每个容器都作详细介绍。
只是从中挑选几个典型的容器,在下面的几个小节中进行具体的讲解。
21.2.2vector
向量容器vector是STL中最简单且最典型的一个。
它在标准C++里,是一个定义在命名空间std中的模版类(由<
头文件给出)。
1.定义
namespacestd{//取自C++2003标准(节选)
template<
classT,classAllocator=allocator<
>
classvector{
public:
……
//types:
类型
typedefimplementationdefinediterator;
//迭代器T*
typedefTvalue_type;
//元素类型
typedefAllocatorallocator_type;
//分配器类型
typedefstd:
:
reverse_iterator<
iterator>
reverse_iterator;
//反向迭代器
explicitvector(constAllocator&
=Allocator());
//构造函数
˜vector();
//析构函数
//iterators:
迭代器
iteratorbegin();
//指向首元素
iteratorend();
//指向尾元素后的一个位置
reverse_iteratorrbegin();
//指向反向序列的首元素
reverse_iteratorrend();
//指向反向序列尾元素后的一个位置
//capacity:
容量
size_typesize()const;
//元素个数
boolempty()const;
//清空
//elementaccess:
元素访问
referenceoperator[](size_typen);
//下标运算符重载(不带检查的访问)
referenceat(size_typen);
//带检查的访问
referencefront();
//首元素
referenceback();
//尾元素
//modifiers:
修改方法
//堆栈操作:
voidpush_back(constT&
x);
//在尾部加入元素
voidpop_back();
//从尾部删除元素
//表操作:
iteratorinsert(iteratorposition,constT&
//在指定位置插入元素
iteratorerase(iteratorposition);
//删除指定位置的元素
voidclear();
//删除所有元素
……
};
//比较运算符重载:
==、<
、!
=、>
、>
=、<
=、、、
classT,classAllocator>
//相等
booloperator==(constvector<
T,Allocator>
&
x,constvector<
y);
//小于
booloperator<
(constvector<
……
//specializedalgorithms:
专用算法
//交换向量x与向量y的句柄
voidswap(vector<
x,vector<
}
在C++的标准库中,还专门化了一个布尔型向量的模版类(带有分配器参数):
classAllocator>
classstd:
vector<
bool,All
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- windows 编程 技术 21 STL
![提示](https://static.bdocx.com/images/bang_tan.gif)