深入解析C++ STL中的常用容器_C 语言

STL是C/C++开发中一个非常重要的模板,而其中定义的各种容器也是非常方便我们大家使用。下面,我们就浅谈某些常用的容器。这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点。STL中的常用容器包括:顺序性容器(vector、deque、list)、关联容器(map、set)、容器适配器(queue、stac)。

1、顺序性容器

(1)vector
vector是一种动态数组,在内存中具有连续的存储空间,支持快速随机访问。由于具有连续的存储空间,所以在插入和删除操作方面,效率比较慢。vector有多个构造函数,默认的构造函数是构造一个初始长度为0的内存空间,且分配的内存空间是以2的倍数动态增长的,即内存空间增长是按照20,21,22,23.....增长的,在push_back的过程中,若发现分配的内存空间不足,则重新分配一段连续的内存空间,其大小是现在连续空间的2倍,再将原先空间中的元素复制到新的空间中,性能消耗比较大,尤其是当元素是非内部数据时(非内部数据往往构造及拷贝构造函数相当复杂)。vector的另一个常见的问题就是clear操作。clear函数只是把vector的size清为零,但vector中的元素在内存中并没有消除,所以在使用vector的过程中会发现内存消耗会越来越多,导致内存泄露,现在经常用的方法是swap函数来进行解决:

复制代码 代码如下:

vector<int> V;
V.push_back(1);
V.push_back(2);
V.push_back(1);
V.push_back(2);
vector<int>().swap(V);
//或者 V.swap(vector<int>());

利用swap函数,和临时对象交换,使V对象的内存为临时对象的内存,而临时对象的内存为V对象的内存。交换以后,临时对象消失,释放内存。

(2)deque
deque和vector类似,支持快速随机访问。二者最大的区别在于,vector只能在末端插入数据,而deque支持双端插入数据。deque的内存空间分布是小片的连续,小片间用链表相连,实际上内部有一个map的指针。deque空间的重新分配要比vector快,重新分配空间后,原有的元素是不需要拷贝的。

(3)list
list是一个双向链表,因此它的内存空间是可以不连续的,通过指针来进行数据的访问,这使list的随机存储变得非常低效,因此list没有提供[]操作符的重载。但list可以很好地支持任意地方的插入和删除,只需移动相应的指针即可。

(4)在实际使用时,如何选择这三个容器中哪一个,应根据你的需要而定,一般应遵循下面的原则:
1) 如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
2) 如果你需要大量的插入和删除,而不关心随即存取,则应使用list
3) 如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque

2、关联容器

(1)map
map是一种关联容器,该容器用唯一的关键字来映射相应的值,即具有key-value功能。map内部自建一棵红黑树(一种自平衡二叉树),这棵树具有数据自动排序的功能,所以在map内部所有的数据都是有序的,以二叉树的形式进行组织。

这是map的模板:
template < class Key, class T, class Compare= less<Key>, class Allocator=allocator< pair<const Key,T> > > class map;

从模板中我们可以看出,再构造map时,是按照一定的顺序进行的。map的插入和删除效率比其他序列的容器高,因为对关联容器来说,不需要做内存的拷贝和移动,只是指针的移动。由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑色),所以map的其中的一个缺点就是比较占用内存空间。

(2)set
set也是一种关联性容器,它同map一样,底层使用红黑树实现,插入删除操作时仅仅移动指针即可,不涉及内存的移动和拷贝,所以效率比较高。set中的元素都是唯一的,而且默认情况下会对元素进行升序排列。所以在set中,不能直接改变元素值,因为那样会打乱原本正确的顺序,要改变元素值必须先删除旧元素,再插入新元素。不提供直接存取元素的任何操作函数,只能通过迭代器进行间接存取。

set模板原型:
template <class Key, class Compare=class<Key>, class Alloc=STL_DEFAULT_ALLOCATOR(Key) > class set;

set支持集合的交(set_intersection)、差(set_difference)、并(set_union)及对称差(set_symmetric_difference) 等一些集合上的操作。

3、容器适配器

(1)queue
queue是一个队列,实现先进先出功能,queue不是标准的STL容器,却以标准的STL容器为基础。queue是在deque的基础上封装的。之所以选择deque而不选择vector是因为deque在删除元素的时候释放空间,同时在重新申请空间的时候无需拷贝所有元素。

其模板为:
template < TYPENAME _Sequence="deque<_TP" typeneam _Tp,> > class queue;

(2)stack
stack是实现先进后出的功能,和queue一样,也是内部封装了deque,这也是为啥称为容器适配器的原因吧(纯属猜测)。自己不直接维护被控序列的模板类,而是它存储的容器对象来为它实现所有的功能。stack的源代码原理和实现方式均跟queue相同。

时间: 2025-01-30 06:57:17

深入解析C++ STL中的常用容器_C 语言的相关文章

浅析STL中的常用算法_C 语言

一.非变异算法 是一组不破坏操作数据的模板函数,用来对序列数据进行逐个处理.元素查找.子序列搜索.统计和匹配.非变异算法具有极为广泛的适用性,基本上可应用与各种容器. 1查找容器元素find 它用于查找等于某值的元素.它在迭代器区间[first,last)(闭开区间)上查找等于value值的元素,如果迭代器i所指的元素满足*i=value,则返回迭代器i:未找到满足条件的元素,返回last.函数原型:find( v1.begin(), v1.end(), num_to_find ); 复制代码

解析C++编程中的bad_cast异常_C 语言

由于强制转换为引用类型失败,dynamic_cast 运算符引发 bad_cast 异常.语法 catch (bad_cast) statement 备注 bad_cast 的接口为: class bad_cast : public exception { public: bad_cast(const char * _Message = "bad cast"); bad_cast(const bad_cast &); virtual ~bad_cast(); }; 以下代码包含

深入解析C++编程中的静态成员函数_C 语言

C++静态成员函数 与数据成员类似,成员函数也可以定义为静态的,在类中声明函数的前面加static就成了静态成员函数.如 static int volume( ); 和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分. 如果要在类外调用公用的静态成员函数,要用类名和域运算符"::".如 Box::volume( ); 实际上也允许通过对象名调用静态成员函数,如 a.volume( ); 但这并不意味着此函数是属于对象a的,而只是用a的类型而已. 与静态数据成员不同,静态成

STL中的常用的vector,map,set,sort, list用法笔记 .

原帖地址:http://hi.baidu.com/yanfei_1/blog/item/a0a538331f5256f91a4cffba.html C++的标准模板库(Standard Template Library,简称STL)是一个容器和算法的类库.容器往往包含同一类型的数据.STL中比较常用的容器是vector,set和map,比较常用的算法有Sort等..一. vector1.声明:          一个vector类似于一个动态的一维数组.          vector<int>

STL中的set容器的一点总结

1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作.vector封装数组,list封装了链表,map和set封装了二叉树等,在封装这些数据结构的时候,STL按照程序员的使用习惯,以成员函数方式提供的常用操作,如:插入.排序.删除.查找等.让用户在STL使用过程中,并不会感到陌生. 关于set,必须说明的是set关联式容器.set作为一个容器也是

【温故而知新】C和C++6:STL中的vector容器

向量容器vector是STL中提供的最常用的容器之一,提供了随机访问数组的功能,可以实现对内部元素的随机访问以及方便地在末尾插入和删除数据.vector可以十分方便地实现数据结构中数组.堆栈功能,而且不需要手动编写管理数据结构的相关函数.其定义在头文件<vector>中. 对vector中的元素进行赋值: 向vector中存放数据主要有两种方法,其一是使用push_back函数逐个在vector末尾添加数据:采用这种方法不需要对容器进行初始内存分配,可以直接从一个空的容器开始操作,但是只能依次

【温故而知新】C和C++8:STL中的list容器

STL提供的list容器实现了双向链表的功能.因此,list容器中的各个元素都是双向链表中的节点,可以很方便地插入和删除元素,但是无法对容器中的元素进行随机存取,必须从容器的头部或尾部遍历.list容器在序列中的任何位置增删元素都是非常高效率的,并可以在需要的时候任意改变自身容量的大小. 1.list容器的定义: 关于如何构造一个list对象,STL提供了多种构造方法: list<type> name;//构建一个空对象 list<type> name(size);//构建一个初始

详细解析C语言中的开方实现_C 语言

关于C语言中的开方计算,首先想到的当然是sqrt()函数,让我们先来回顾一下它的基本用法: 头文件:#include <math.h> sqrt() 用来求给定值的平方根,其原型为: double sqrt(double x); 参数 x 为要计算平方根的值. 如果 x < 0,将会导致 domain error 错误,并把全局变量 errno 的值为设置为 EDOM. 返回值 返回 x 平方根. 注意,使用 GCC 编译时请加入-lm. 实例计算200 的平方根值. #include

【温故而知新】C和C++9:STL中的set容器

1.Set/MultiSet容器的定义和创建 Set即集合类,可以在程序中按照次序来保存一组数值.在集合中,元素的关键字和数据二者相同,该集合本质上就是一个有序的排列.Multiset与set不同的是,前者其中的元素允许重复而后者不允许. Set对象采用二叉树结构储存,该结构的优点是查询效率高,并且有利于插入和删除操作. Set定义了多种实例化的方法,其中比较常用的有: set<int> s0;//定义一个空的set set<int, greater<int>> s1;