C++ Primer学习笔记(11)——(转)c++ 标准库的各种容器(vector,deque,map,set,unordered_map,unordered_set,list)的性能考虑

转载 2015年07月08日 10:01:39

声明:此文章转自truexf 的博客,自觉他总结的比我好,故收藏于此,共学习之用。谢谢大神分享!

一、vector

vector采用一段连续的内存来存储其元素,向vector添加元素的时候,如果容量不足,vector便会重新malloc一段更大的内存,然后把原内存中的数据memcpy到新的内存中,并free原内存块,然后将新元素加入。vector的元素插入性能跟以下几个要素关系重大:

1.插入的位置

头部插入:将所有元素后移,然后将新元素插入

中间插入:将插入点后面的元素后移,然后插入新元素

尾部插入:将新元素直接插入尾部

尾部插入无疑是最快的,头部插入最慢,中间插入次之,慢的点在于插入前要移动内存。

删除元素也是同样的道理。

2.保留空间大小

如果插入元素是,空间不足将导致重新malloc以及一系列的内存拷贝。如果使用者能对容量有预期,那么采用reserve()来预先分配内存,将大大的提高性能。

3.内存扩展算法的库实现相关

在空间不足导致需要重新malloc的时候,不同的库实现有很大的不同,往往特定平台的实现会结合操作系统的平台特性以及malloc算法,提供相当优秀的内存扩展算法,在百万次vector的插入操作中,不提供reserve()的情况向,性能表现非常优秀。接近于使用了reserve()的情况。

因为vector采用连续的内存存储其元素,因此其支持元素的下标法随机访问,且时间复杂度是常量0;

如果是查找元素,vector的find()成员函数对元素进行查找时是采用从头到尾扫描的方式,他时间复杂度是O(n),如果vector要应付查找的性能需求,那么应该采取排序的vector,利用算法库的getlowerbound()进行元素的有序插入,利用binary_search()对元素进行二分查找。这种情况下其查找性能不输于基于红黑树的set和map,更是令list望尘莫及。

综述,vector适用于尾部插入,但是此时无法兼顾查找的性能,因为二分查找的vector要求重新排序,或者要求vector在插入时就保持有序,这样就无法做到尾部插入。

但是vector作为动态数组的替代,已经足够优秀。

二、deque

deque采用多块内存串起来的方式提供其元素的存错,每一个内存块存储多个元素,每一块内存存储的元素个数相同,这是他不同于vector采用一块内存来存错所有的元素的方式。这样带来的好处是:

首先,头部插入和尾部插入/删除元素的成本是一样,弥补了vector再头部插入元素性能不佳的问题;

其次,对于vector的一个内存块的模式,当有巨大数量的元素,操作系统的大内存分配和赋值时很缓慢的,而且deque的方式就不会带来这个问题。

缺点是:

首先对元素的访问需要经过两个层次,第一次找到元素所在的内存块,第二次找到块中的元素。不过这个时间几乎是可以忽略,除非对性能要求极其苛刻。

其次,对其进行排序,以及排序后的查找会比较慢,想象知名的排序算法,都是针对一段连续内存进行下标访问,而deque是断续的内存块组成。同样排序后的折半查找也无法利用下标直接访问自然性能大打折扣。

三、list

list很简单,他就是个双向链表。每一个节点的内存都是独立的。理论上,其优点是任何位置的插入删除元素操作都是非常块的。缺点是不适合用于元素的查找,因为他只能是扫描的方式。根据实际的测试情况来看,我认为list不值得一用,因为节点的频繁新增与删除将导致大量重复的内存分配和释放操作。而实际上,操作系统以及运行库的内存分配与释放频率和策略才是影响stl各大容器的性能最关键的点。

四、map/multi_map/set/multi_set

这四个数据结构是采用平衡树(红黑树)实现其元素在内存中的存储。理论上(与list一样是理论上)他们的性能是很高,而且在插入/删除与元素查找上是的平衡点掌握的相当好的,具体的算法复杂度可参考红黑树算法文献,但是同样基于“操作系统以及运行库的内存分配与释放频率和策略才是影响stl各大容器的性能最关键的点”这一法则,他们在理论之外,实际的应用中,总是表现得不是太好。

五、散列容器
unordered_map/unordered_set/unordered_multi_map/unordered_multi_set

c++11引入的散列容器,散列容器具有不稳定性:他依赖于实际所使用的散列算法。而针对不同的元素数量,不同的散列算法具有相当大的性能差异。

所以,理论上(同样是理论上)他们的算法时间复杂度是近乎“常量”(如果要处理冲突那就不是了)。但时间上对于一般用户使用起来可能会带来风险。除非你对所使用的散列算法和元素数量都有很好的预估。在我一些简单的测试(采用int元素类型,采用std的默认散列函数)中,散列容器的性能是排名垫底的。

六、“内存分配与释放频率和策略才是影响stl各大容器的性能最关键的点”

这点非常重要。不同的操作系统,不同的运行库,他的虚拟内存管理算法,以及运行库的malloc和free的内部实现都是有差异的。如何找出最有效率的使用标准库容器的方式,一定要结合这一点进行大量的测试才能得出。

有一点可以确认的是:各个标准库的实现,已经是在遵循c++标准的基础上,在性能和适用性上可以说做到了极致。因此很多人总想自己造重复的轮子是大可不必。理解好各种容器的实现原理,再结合实际应用的需求,选择合适的容器,以及容器的使用方式,才是上上之策。

c++ 标准库的各种容器(vector,deque,map,set,unordered_map,unordered_set,list)的性能考虑

c++ 标准库的各种容器(vector,deque,map,set,unordered_map,unordered_set,list)的性能考虑   一、vector vector采用一段连续的...
  • truexf
  • truexf
  • 2013年12月13日 15:55
  • 12793

【C++】【总结】unordered_map,unordered_set,map和set的用法和区别

unordered_map 头文件:#include 介绍:std::unordered_map 本来就是以key来查找value而设计。 方法: Insert...
  • zjajgyy
  • zjajgyy
  • 2017年03月25日 11:30
  • 1842

比较测试map、unodered_map、unordered_set性能效率,整型数值查找

测试环境: centos 6.5 gcc 4.4.3
  • u010524448
  • u010524448
  • 2014年07月12日 11:41
  • 1819

stl容器区别(内存布局和使用场合): vector list deque set map

set 和map都是无序的保存元素,只能通过它提供的接口对里面的元素进行访问。  set:集合, 用来判断某一个元素是不是在一个组里面,使用的比较少  map:映射,相当于字典,把一个值映射成另一个值...
  • u012223913
  • u012223913
  • 2016年04月22日 22:27
  • 1276

C++三种容器:list、vector和deque的区别

在写C++程序的时候会发现STL是一个不错的东西,减少了代码量,使代码的复用率大大提高,减轻了程序猿的负担。还有一个就是容器,你会发现要是自己写一个链表、队列,或者是数组的时候,既要花时间还要操心怎么...
  • gogoky
  • gogoky
  • 2016年05月06日 17:35
  • 10426

c++ unordered_map/set自定义对象的hash

平时很少用到unordered_set的自定义对象,常用的都是unordered_map, unordered_map之类的内建数据类型。前段时间在写一个编码库的时候,用到了自定义对象,却无从下手,在...
  • lipeng08
  • lipeng08
  • 2017年01月11日 16:39
  • 1828

STL中list,vector,deque,map,set区别、联系和使用场景原理

一、Vector:动态数组       vector和built-in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随机存取,即[]操作符,但由于它的内存空间是连...
  • caojunhao123
  • caojunhao123
  • 2013年09月22日 20:35
  • 2086

C/C++--STL中list,vector,deque,map,set区别、联系和使用场景

原谅地址:http://www.lifecrunch.biz/archives/202 vector和built-in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此 它...
  • zlQQhs
  • zlQQhs
  • 2014年06月16日 20:46
  • 3139

c++ list, vector, map, set 区别与用法比较

List封装了链表,Vector封装了数组, list和vector得最主要的区别在于vector使用连续内存存储的,他支持[]运算符,而list是以链表形式实现的,不支持[]。 Vector对...
  • alex_xhl
  • alex_xhl
  • 2014年07月11日 11:01
  • 32543

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

申明,本文非笔者原创,原文转载自:http://blog.sina.com.cn/s/blog_533074eb01017zq2.html 在STL中基本容器有: vector、li...
  • carson2005
  • carson2005
  • 2015年04月29日 11:08
  • 2086
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Primer学习笔记(11)——(转)c++ 标准库的各种容器(vector,deque,map,set,unordered_map,unordered_set,list)的性能考虑
举报原因:
原因补充:

(最多只允许输入30个字)