荥阳市论坛

注册

 

发新话题 回复该主题

STL中的一些概念 [复制链接]

1#

前言

在学习STL编程的前提,是需要了解C++模板的概念。模板是C++程序设计语言中的一个重要特征,而标准模板库正是基于此特征。标准模板库使得C++编程语言在有了同Java一样强大的类库的同时,保有了更大的可扩展性。

、什么是STL

STL,英文全称standardtemplatelibrary,中文可译为标准模板库或者泛型库,其包含有大量的模板类和模板函数,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库(C++StandardLibrary)中,是ANSI/ISOC++标准中最新的也是极具革命性的一部分。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法。为广大C++程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。

简单的总结:

复用性的提升。(众多的组件。vector、list等)

是依据泛型思维架设起来的一个概念结构

2、六大组件

容器(Container):一些封装数据的模板类。如Vector、list、deque、set、map等,主要用来存放数据。为了访问容器中的数据,可以使用由容器类输出的迭代器,就体积而言,这一块是非常巨大的。

算法(Algorithm):算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。STL提供了非常多(大约00个)的数据结构算法,它们都被设计成一个个的模板函数,这些算法在std命名空间中定义,其中大部分算法都包含在头文件中,少部分位于头文件中。

迭代器(Iterator):在C++STL中,对容器中数据的读和写,是通过迭代器完成的,扮演着容器和算法之间的胶合剂。是所谓的“泛型指针”。为了保持代码的封装性,每一个STL容器都有自己特有的迭代器,这就意味着只有容器的设计着才知道怎么遍历访问自己的元素。

仿函数(Functor):重载了operator()运算符的类或者模板类,如果一个类将()运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象(又称仿函数)。行为类似函数。

适配器(Adaptor):可以使一个类的接口(模板的参数)适配成用户指定的形式,从而让原本不能在一起工作的两个类工作在一起。值得一提的是,容器、迭代器和函数都有适配器。

分配器(allocator):为容器类模板提供自定义的空间申请和释放功能,实现动态控件配置、管理、释放。由于往往只有高级用户才有改变内存分配策略的需求,因此内存分配器对于一般用户来说,并不常用。

3、迭代器

在设计模式中这样定义:提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。简单的讲,就是提供了一个索引,这个索引只能顺序的访问,并且不知道该对象内部的表示。

而STL的中心思想:将容器和算法分开,独立设计,最后在撮合在一起。撮合的中间件也就是迭代器,被称作胶合剂。

迭代器是一种类似于指针的对象。因此迭代器最重要的便是对operator-和operator*的重载。

4、容器

在实际的开发过程中,容器的选择并不是随意就好,容器的选择往往决定着对这些容器进行增删改查操作的复杂度和时间消耗。而如果程序中对时效的要求比较高时,合理的选择容器就会尤为重要。

简单的来说,容器就是一些模板类的集合,容器封装的是组织数据的方法,也就是常说的数据结构。STL提供有3类标准容器。

序列容器:序列容器,是指元素在容器中的位置与元素的值无关,是其中的元素是可序的,但并不一定是有序的。每个元素的位置取决于插入容器的时机和地点。STL中的序列容器包括:vector、list、deque、stack、queue、priority-queue等。其中stack和queue只是将deque使用适配器进行了封装。

有序关联容器:关联式容器,是不是会想到关联式数据库,每个元素都有一个键(key)和值(value)一一对应。元素的位置按照特定的规则顺序(默认是从小到大)排列好,不管插入的时机和地点。STL中的关联式容器包括:set/multiset、map/multimap。

哈希容器:C++新加入4种关联式容器,分别是unordered_set哈希集合、unordered_multiset哈希多重集合、unordered_map哈希映射以及unordered_multimap哈希多重映射。和排序容器不同,哈希容器中的元素是未排序的,元素的位置由哈希函数确定。

有序关联容器和哈希容器统称为关联容器。

上面三类容器的存储方式是完全不同的,因此在使用不同容器完成相同的操作时的效率也是完全不一样的。在实际使用时,根据不同的功能,选择合适的容器,显得尤为重要。

容器的选择建议:

如果程序要求随机访问元素,应使用vector或deque;

如果有很多小的元素,且空间的额外开销很重要,则不要使用list或forward_list(链表);

如果程序需要在头尾插入/删除元素,且不会在中间插入元素,则使用deque;

如果需要大量的随机的插入和删除元素,不关心随机存取的效率,使用list;

如果打算查找一个元素是否存在于某集合中(遍历),唯一存在的情况使用set,不唯一存在的情况使用multiset;

如果打算存储数据字典(排序),并且要求方便地根据key找到value,一对一的情况使用map,一对多的情况使用multimap;

如果要求很快的查找速度(通过键值),选择使用unordered_map或unordered_set;

PS.如果实在不确定使用哪种元素,那么使用vector或list.

5、算法

STL提供了一些常见的算法,如排序和搜索等。这些算法与数据结构的实现进行了分离。因此,用于也可对自定义的数据结构使用这些算法,只需让这些自定义的数据结构拥有算法所预期的迭代器。

查找算法(3个):adjacent_find、count、find、search

排序和通用算法(4个):merge、reverse、sort

删除和替换算法(5个):copy、remove、swap、replace

排列组合算法(2个):next_permutation、prev_permutation

算术算法(4个):accumulate、partial_sum

生成和异变算法(6个):fill、for_each、transform

关系算法(8个):equal、includes、max、min、mismatch

集合算法(4个):set_union、set_intersection、set_difference

堆算法(4个):make_heap、pop_heap

6、仿函数

又名函数对象。就实现而言,仿函数其实就是一个“行为类似函数”的对象。实现就是类中实现一个operator()。我们就能使用如下的调用:

#includeiostream#includealgorithmusingnamespacestd;templatetypenameTclassdisplay{public:voidoperator()(constTx){coutx""endl;}};intmain(intargc,char*argv[]){intdata[]={,2,3,4,5};for_each(data,data+5,displayint());return0;}

STL中仿函数的分类:以操作数的个数来划分,分为一元和二元仿函数。以功能划分:算数运算、关系运算、逻辑运算。

7、适配器

适配器这个概念在设计模式中这样定义:将一个类的接口转换成客户希望的另外一个类的接口。Adapt模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。STL中所提供的适配器。可分为以下几种:

应用于容器:STL提供的两个容器,queue和stack,本质上都是一种适配器。修饰deque的接口而形成另一种容器。

应用与迭代器:STL提供了许多应用于迭代器身上的适配器。包括insertiterators,reverseiterators,iostreamiterators。

应用于仿函数:数量比较庞大的族群。通过他们之间的绑定、组合、修饰能力,创造出各种可能的表达式,搭配STL的算法一起。

8、分配器

从STL的运用角度来看,分配器是最不需要的一个东西,因为我们几乎用不到。隐藏在容器之后,提供自定义的控件的申请、管理、释放。

allocator是空间分配器,并不是单纯的内存分配器,是因为可以在磁盘上或其他辅助存储介质。

预览时标签不可点收录于话题#个上一篇下一篇
分享 转发
TOP
发新话题 回复该主题