STL容器的本质
http://blog.sina.com.cn/s/blog_4d3a41f40100eof0.html
最近在学习unordered_map里面的散列函数和相等函数怎么写.学习过程中看到了一个好帖子.学习学习
标准STL序列容器:vector、string、deque和list
标准STL关联容器:set、multiset、map和multimap
非标准序列容器slist和rope
非标准关联容器hash_set、hash_multiset、hash_map和hash_multimap
rope是绳子的意思,string是线的意思,rope就是一个重量级的string。
STL不同容器的实现是差别很大的,但它们都有一个数据结构原型,都具备各自的特性,最明显的是同一方法在不同容器中的效率差别很大。因此认清STL常用容器的本质,你才不会在你的应用中选错容器。
std::list的本质是链表
它的优势是在头和尾巴的插入和删除很快速
它的缺点就是随机访问能力差,因为它是挨个访问元素的
如果你的应用对随机访问效率有较高要求,那list不是你的首选。最夸张的是list的size()是从头到尾挨个数一遍的。
std::vector的本质是红黑树(一种特殊的平衡二叉树)
它的优点是随机访问能力强,红黑树的原因
它的缺点是非最后一个元素的插入和删除速度慢,为了保证随机访问速度,插入和删除对会对红黑树做调整
一般情况下我们把vector当成一个数组使用,只不过这个数组的大小可以增加,所以不要贪心只用这些功能就够了。贪心你就会造成效率的降低。
vector容量的增长也是有开销的,如果你频繁的push_back(),还不如先一次性的多分配一些reserve()。注意reserve()和resize()是不一样的,一个调整预留空间,一个是调整元素个数。
(此部分会继续更新)
此外《Effective+STL》为我们提供了一些使用原则:
- 你需要“可以在容器的任意位置插入一个新元素”的能力吗?如果是,你需要序列容器,关联容器做不到。
 - 你关心元素在容器中的顺序吗?如果不,散列容器就是可行的选择。否则,你要避免使用散列容器。
 - 必须使用标准C++中的容器吗?如果是,就可以除去散列容器、slist和rope。
 - 你需要哪一类迭代器?如果必须是随机访问迭代器,在技术上你就只能限于vector、deque和string,但你也可能会考虑rope(关于 rope的更多信息在条款50)。如果需要双向迭代器,你就用不了slist(参见条款50)和散列容器的一般实现(参见条款25)。
 - 当插入或者删除数据时,是否非常在意容器内现有元素的移动?如果是,你就必须放弃连续内存容器(参见条款5)。
 - 容器中的数据的内存布局需要兼容C吗?如果是,你就只能用vector(参见条款16)。
 - 查找速度很重要吗?如果是,你就应该看看散列容器(参见条款25),排序的vector(参见条款23)和标准的关联容器——大概是这个顺序。
 - 你介意如果容器的底层使用了引用计数吗?如果是,你就得避开string,因为很多string的实现是用引用计数(参见条款13)。你也不能用 rope,因为权威的rope实现是基于引用计数的(参见条款50)。于是你得重新审核你的string,你可以考虑使用vector <char>。
 - 你需要插入和删除的事务性语义吗?也就是说,你需要有可靠地回退插入和删除的能力吗?如果是,你就需要使用基于节点的容器。如果你需要多元素插入 (比如,以范围的方式——参见条款5)的事务性语义,你就应该选择list,因为list是唯一提供多元素插入事务性语义的标准容器。事务性语义对于有兴 趣写异常安全代码的程序员来说非常重要。(事务性语义也可以在连续内存容器上实现,但会有一个性能开销,而且代码不那么直观。要了解这方面的知识,请参考 Sutter的《Exceptional C++》的条款17[8]。)
 - 你要把迭代器、指针和引用的失效次数减到最少吗?如果是,你就应该使用基于节点的容器,因为在这些容器上进行插入和删除不会使迭代器、指针和引用失效(除非它们指向你删除的元素)。一般来说,在连续内存容器上插入和删除会使所有指向容器的迭代器、指针和引用失效。
 - 你需要具有有以下特性的序列容器吗:1)可以使用随机访问迭代器;2)只要没有删除而且插入只发生在容器结尾,指针和引用的数据就不会失效?这个 一个非常特殊的情况,但如果你遇到这种情况,deque就是你梦想的容器。(有趣的是,当插入只在容器结尾时,deque的迭代器也可能会失 效,deque是唯一一个“在迭代器失效时不会使它的指针和引用失效”的标准STL容器。)
 - 这些问题几乎不是事情的完结。比如,它们没有关注不同的容器类型使用不同的内存配置策略(条款10和14讨论了这些策略的一些方面)。但是,它们 已经足够是你信服了,除非你对元素顺序、标准的一致性、迭代器能力、内存布局和C的兼容性、查找速度、因为引用计数造成的行为不规则、事务性语义的轻松实 现和迭代器失效的条件没兴趣,你得在容器操作的算法复杂度上花更多的考虑时间。当然这样的复杂度是重要的,但这离整个故事很远。
 
在程序的世界里面,也是有得必有失,没有完美的东西,你所要决定的是在开发效率和运行效率间找一个平衡。而这个的前提是你要熟悉你所用的东西。
STL容器的本质的更多相关文章
- 转:STL容器里存放对象还是指针
		
一.问题的引出: 容器可以存放对象,可以存放指针,这里要谈的是两者的使用问题.就是什么时候存放对象更好,什么时候存放指针更好? 二.问题的分析过程: 1. 首先说下stl容器的工作方式 对于内建类 ...
 - STL容器总结
		
一. 种类: 标准STL序列容器:vector.string.deque和list. 标准STL关联容器:set.multiset.map和multimap. 非标准序列容器slist和rope.sl ...
 - STL容器之一vector
		
STL中最简单也是最有用的容器之一是vector<T>类模板,称为向量容器,是序列类型容器中的一种. 1.vector<T> 对象的基本用法(1)声明:vector<ty ...
 - Sword STL容器分类介绍
		
标准STL序列容器:vector.string.deque和list. 标准STL关联容器:set.multiset.map和multimap. 非标准序列容器slist和rope.slist是一个单 ...
 - C++ STL 容器概述
		
在STL编程中,容器是经常用到的一种数据结构,在C++标准库中,容器分为: 序列式容器 关联式容器 二者本质区别在于,序列式容器是通过元素在容器中的位置进行顺序存储和元素访问.关联容器则是通过键[ke ...
 - STL容器
		
啦啦啦,今天听啦高年级学长讲的STL容器啦,发现有好多东西还是有必要记载的,毕竟学长是身经百战的,他在参加各种比赛的时候积累的经验可不是一天两天就能学来的,那个可是炒鸡有价值的啊,啊啊啊啊啊 #inc ...
 - c++ stl容器set成员函数介绍及set集合插入,遍历等用法举例
		
c++ stl集合set介绍 c++ stl集合(Set)是一种包含已排序对象的关联容器.set/multiset会根据待定的排序准则,自动将元素排序.两者不同在于前者不允许元素重复,而后者允许. 1 ...
 - STL容器删除元素的陷阱
		
今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector< ...
 - 【转】c++中Vector等STL容器的自定义排序
		
如果要自己定义STL容器的元素类最好满足STL容器对元素的要求 必须要求: 1.Copy构造函数 2.赋值=操作符 3.能够销毁对象的析构函数 另外: 1. ...
 
随机推荐
- Java自学成长路线(转载)
			
JAVA自学之路 一:学会选择 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机.嵌入式.游戏.3G.测试等. JAVA是一种平台,也是一种程序设计语言,如何学好程序设计不仅 ...
 - C#_delegate - 异步调用实例 BeginInvoke EndInvoke event
			
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
 - 马上学Android开发在线视频教程全集
			
马上学Android开发视频教程全集 马上学Android开发[马上学Android]安卓开发视频教程 001 Androi 马上学Android开发[马上学Android]安卓开发视频教程 002 ...
 - Objective-C中NSArray和NSMutableArray是如何使用的?
			
Objective-C的数组比C++,Java的数组强大在于,NSArray保存的对象可以是不同的对象.但只能保存对象,int ,char,double等基本数据类型不能直接保存,需要通过转换成对象才 ...
 - 关于Arrays类总结
			
Arrays是java中的工具类,其中所有的方法都是static.类名就可以直接调用其中的方法. 本文部分引用自: http://www.importnew.com/8952.html Arrays. ...
 - linux系统安装对硬件有什么要求
			
Linux系统对你的硬件要求不是很高,你可以参照你的系统上面的参数进行对照,Linux系统的初衷就是以最低的配置完成最高的性能,随意,现在的计算机都可以安装这个系统的,你不要顾虑多了,但是分区你不用系 ...
 - Linux忘记mysql的root密码的解决办法
			
1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以任意地登录 ...
 - [转载]ubuntu Atheros Communications Device 1083 驱动
			
Ubuntu 版本: Ubuntu server 10.10 在2016-03-26 上午时,拆开公司一台server电脑的CPU风扇不转,电源都烧掉了(潮湿的原因)... 在2016-03-28 打 ...
 - Python(2.7.6) 迭代器
			
除了对列表.集合和字典等进行迭代,还能对其他对象进行迭代:实现 __iter__ 方法的对象.例如, 文件对象就是可迭代的: >>> dir(file) ['__class__', ...
 - ios推送基于YII第三方组件的类库
			
<?php namespace common\extensions\push; use \CComponent; /** * @desc iphone推送的接口程序 */ class ApnsP ...