STL中vector,list,deque和map的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL中vector,list,deque和map的区别相关的知识,希望对你有一定的参考价值。

参考技术A STL 容器
Visual Studio 2013
其他版本

1(共 1)对本文的评价是有帮助 - 评价此主题
ISO 标准模板库 (STL) 为存储相关对象的集合提供容器。 容器是能够启用容器中允许的对象规范的模板类。

说明

本文不适用于 STL/CLR。 有关更多信息,请参见 STL/CLR 库参考。

STL 中的容器可以分为三个类别:序列容器、关联容器和容器适配器。

序列容器

序列容器维护你指定的插入元素的顺序。
vector 容器的行为类似于数组,但可以根据要求自动增长。 它可以随机访问、连续存储,长度也非常灵活。 基于上述和其他原因,vector 是多数应用程序的首选序列容器。 有关更多信息,请参见 vector 类。
array 容器具备 vector 的某些优点,但长度不够灵活。 有关更多信息,请参见 array 类 (STL)。
deque(双端队列)容器支持在容器的起点和终点进行快速插入和删除。 它享有 vector 随机访问和长度灵活的优点,但是不具备连续性。 有关更多信息,请参见 deque 类。
list容器是双向链表,在容器内的任意位置启用了双向访问、快速插入和快速删除,但是你不能随机访问此容器中的元素。 有关更多信息,请参见 list 类。
forward_list 容器是单独链表,list 的向前访问版本。 有关更多信息,请参见 forward_list 类。

关联容器

在关联容器中,按照预定义的顺序插入元素,例如按升序排序。 无序的关联容器也可用。 关联容器可分为两个子集:映射和组集。
map,有时称为字典,包含键/值对。 键用于对序列排序,值与该键关联。 例如,map可能包含许多键(代表文本中每个独特的单词)和相应的值(代表每个单词在文本中出现的次数)。 map的无序版本是 unordered_map。有关更多信息,请参见map 类和unordered_map 类。
set仅是按升序排列每个元素的容器,值也是键。 set的无序版本是 unordered_set。 有关更多信息,请参见set 类和unordered_set 类。
map 和 set 都仅允许将键或元素的一个实例插入容器中。 如果需要元素的多个实例,请使用multimap或multiset。 无序版本是 unordered_multimap 和 unordered_multiset。 有关更多信息,请参见 multimap 类、unordered_multimap 类、multiset 类和 unordered_multiset 类。
有序的映射和组集支持双向迭代器,其未排序副本支持向前迭代器。 有关更多信息,请参见迭代器。

容器适配器

容器适配器是序列容器或关联容器的变体,为了简单明确起见,它对接口进行限制。 容器适配器不支持迭代器。
queue容器遵循 FIFO(先进先出)语义。 第一个推送(即插入队列中)的元素将第一个弹出(即从队列中移除)。 有关更多信息,请参见 queue 类。
priority_queue容器也是如此组织,因此具有最高值的元素始终排在队列的第一位。 有关更多信息,请参见 priority_queue 类。
stack容器遵循 LIFO(后进先出)语义。 堆栈上最后推送的元素将第一个弹出。 有关更多信息,请参见 stack 类。
由于容器适配器不支持迭代器,因此无法与 STL 算法一起使用。 有关更多信息,请参见算法。

容器元素的要求

通常,如果插入 STL 容器中的元素可复制,那么这些元素可以是任何对象类型。 只要你不调用尝试复制元素的成员函数,仅可移动的元素(例如,那些类似于 vector<unique_ptr<T>>、使用 unique_ptr<> 创建的元素)会一直工作。
析构函数不允许引发异常。
有序的关联容器(本文之前所述)必须已定义公共比较运算符。(默认情况下,该运算符是 operator<,即使不能与 operator< 共同使用的类型也会受支持。)
容器中的某些操作可能还需要公共默认构造函数和公共等效运算符。 例如,未排序的关联容器需要支持相等性和哈希处理。

http://msdn。microsoft。com/zh-cn/library/1fe2x6kt。aspx

stl容器区别: vector list deque set map及底层实现

在STL中基本容器有: vector、list、deque、set、map

set 和map都是无序的保存元素,只能通过它提供的接口对里面的元素进行访问

set :集合, 用来判断某一个元素是不是在一个组里面,使用的比较少 
map :映射,相当于字典 ,把一个值映射成另一个值,如果想创建字典的话使用它好了 
底层采用的是树型结构,多数使用平衡二叉树实现 ,查找某一值是常数时间,遍历起来效果也不错, 只是每次插入值的时候,会重新构成底层的平衡二叉树,效率有一定影响.

vector、list、deque是有序容器 
1.vector 
vector就是动态数组.它也是在堆中分配内存,元素连续存放,有保留内存,如果减少大小后,内存也不会释放.如果新值>当前大小时才会再分配内存.

它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即[] 操作符,但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝 ,另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。 

对最后元素操作最快(在后面添加删除最快 ), 此时一般不需要移动内存,只有保留内存不够时才需要

 

对中间和开始处进行添加删除元素操作需要移动内存,如果你的元素是结构或是类,那么移动的同时还会进行构造和析构操作,所以性能不高 (最好将结构或类的指针放入vector中,而不是结构或类本身,这样可以避免移动时的构造与析构)。 
访问方面,对任何元素的访问都是O(1),也就是是常数的,所以vector常用来保存需要经常进行随机访问的内容,并且不需要经常对中间元素进行添加删除操作.

相比较可以看到vector的属性与string差不多,同样可以使用capacity看当前保留的内存,使用swap来减少它使用的内存.


总结 
 

需要经常随机访问请用vector

2.list 
list就是双向链表 ,元素也是在堆中存放, 每个元素都是放在一块内存中,它的内存空间可以是不连续的,通过指针来进行数据的访问,这个特点使得它的随机存取变的非常没有效率 ,因此它没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入。

list没有空间预留习惯 ,所以每分配一个元素都会从内存中分配,每删除一个元素都会释放它占用的内存.

list在哪里添加删除元素性能都很高,不需要移动内存,当然也不需要对每个元素都进行构造与析构了,所以常用来做随机操作容器. 
但是访问list里面的元素时就开始和最后访问最快 
访问其它元素都是O(n) ,所以如果需要经常随机访问的话,还是使用其它的好

总结 
如果你喜欢经常添加删除大对象的话,那么请使用list 
要保存的对象不大,构造与析构操作不复杂,那么可以使用vector代替 
list<指针>完全是性能最低的做法,这种情况下还是使用vector<指针>好,因为指针没有构造与析构,也不占用很大内存 

3.deque 
deque是一个双端队列 (double-ended queue),也是在堆中保存内容的 .它的保存形式如下: 
[堆1] 
... 
[堆2] 
... 
[堆3] 
每个堆保存好几个元素,然后堆和堆之间有指针指向,看起来像是list和vector的结合品.

它支持[]操作符,也就是支持随即存取,可以让你在前面快速地添加删除元素,或是在后面快速地添加删除元素,然后还可以有比较高的随机访问速度,和vector的效率相差无几,它支持在两端的操作:push_back,push_front,pop_back,pop_front等,并且在两端操作上与list的效率也差不多。 
在标准库中vector和deque提供几乎相同的接口,在结构上它们的区别主要在于这两种容器在组织内存上不一样,deque是按页或块来分配存储器的,每页包含固定数目的元素.相反vector分配一段连续的内存,vector只是在序列的尾段插入元素时才有效率,而deque的分页组织方式即使在容器的前端也可以提供常数时间的insert和erase操作,而且在体积增长方面也比vector更具有效率

总结: 
vector是可以快速地在最后添加删除元素,并可以快速地访问任意元素 
list是可以快速地在所有地方添加删除元素,但是只能快速地访问最开始与最后的元素 
deque在开始和最后添加元素都一样快,并提供了随机访问方法,像vector一样使用[]访问任意元素,但是随机访问速度比不上vector快,因为它要内部处理堆跳转 
deque也有保留空间.另外,由于deque不要求连续空间,所以可以保存的元素比vector更大,这点也要注意一下.还有就是在前面和后面添加元素时都不需要移动其它块的元素,所以性能也很高。

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

以上是关于STL中vector,list,deque和map的区别的主要内容,如果未能解决你的问题,请参考以下文章

STL中vector,list,deque和map的区别

STL中vector,list,deque和map的区别

stl容器区别: vector list deque set map及底层实现

STL容器用法速查表:list,vector,stack,queue,deque,priority_queue,set,map

STL容器

STL 基本容器