1.容器说明
- Vector特点:连续存储结构,每个元素在内存上是连续的;支持高效的随机访问和在尾端插入/删除操作,但其他位置的插入/删除操作效率低下;相当于一个数组,但是与数组的区别为:内存空间的扩展。vector支持不指定vector大小的存储,但是数组的扩展需要程序员自己写。
vector的内存分配实现原理:
STL内部实现时,首先分配一个非常大的内存空间预备进行存储,即capacity()函数返回的大小,当超过此分配的空间时再整体重新放分配一块内存存储(VS6.0是两倍,VS2005是1.5倍),所以这给人以vector可以不指定vector即一个连续内存的大小的感觉。通常此默认的内存分配能完成大部分情况下的存储。
扩充空间(不论多大)都应该这样做:
1.配置一块新空间
2.将旧元素一一搬往新址
3.把原来的空间释放还给系统
注:vector 的数据安排以及操作方式,与array 非常相似。两者的唯一差别在于空间的利用的灵活性。Array 的扩充空间要程序员自己来写。
优点:
1.随机存取,即[]操作和vector.at()
2.动态操作,push_back()与pop_back()
3.自动调整内存,节省空间
缺点:
1.实现插入与删除操作效率低
2.只能在尾部插入与删除,在头部插入与删除消耗时间规模与容器大小成正比。
3.当动态添加的数据超过默认内存大小时,要进行整体的重新分配,拷贝与释放。
- list特点 非连续存储,具有双链表结构,每个元素维护一对前向和后向指针,因此支持前向/后向遍历。支持高效的随机插入/删除操作,但随机访问效率低下,且由于需要额外维护指针,开销也比较大。每一个结点都包括一个信息快Info、一个前驱指针Pre、一个后驱指针Post。可以不分配必须的内存大小方便的进行添加和删除操作。使用的是非连续的内存空间进行存储,对每个元素分配空间,所以不存在空间不够,重新分配的情况。
优点:
1.内存不连续
2.动态操作,插入与删除效率高
3.可在两端进行pop,push
缺点:
1.不能随机访问,即不支持[]和at()操作
2.相对于vector占用内存多
- deque特点:双端队列
double-end queue
连续存储结构,即其每个元素在内存上也是连续的,类似于vector,不同之处在于,deque提供了两级数组结构, 第一级完全类似于vector,代表实际容器;另一级维护容器的首位地址。这样,deque除了具有vector的所有功能外,还支持高效的首/尾端插入/删除操作。
deque是由一段一段的定量连续空间构成。一旦有需要在deque的前端和尾端增加新空间,便配置一段定量连续空间,串在整个deque的头端或尾端。deque的最大任务就是在这些分段的连续空间上,维护其整体连续的假象,并提供随机存取的接口。避开了“重新配置、复制、释放”的轮回,代价是复杂的迭代器架构。deque是在功能上合并了vector和list。
优点:
1.随机访问,即[]操作和deque.at()
2.插入与删除方便
3.可在双端进行pop,push
缺点:
1.占用内存多。
- set 内部元素唯一,用一棵平衡树结构来存储,因此遍历的时候就排序了,查找也比较快的哦。
- map 一对一的映射的结合,key不能重复。
- stack 适配器,必须结合其他的容器使用,stl中默认的内部容器是deque。先进后出,只有一个出口,不允许遍历。
- queue 是受限制的deque,内部容器一般使用list较简单。先进先出,不允许遍历。
2.vector,list,queue的比较
相同点:
三者都能实现resize()来重新调整容器的大小。
不同点:
1)vector能实现随即存取,即[]操作,而list不能,deque是二者的结合体,也能够实现索引操作[],但效率没有vector高。
2)vector适合在文件的末尾实现删除元素的操作pop_back()与插入操作push_back(),在中间时效率非常低下。而
list可以在容器的任何位置实现插入与删除操作。
原因:vector的元素地址连续,如果在中间插入与删除操作,可能会导致原来的内存地址不足以存储当前的元素,需要重
新分配内存地址,这就需要将原来的所有元素拷贝到新内存,释放旧的内存地址等操作,操作代价高昂。而list元素内存地
址不连续,用指针操作,其本身是一个双向链表,它的高效率体现在插入,删除以及排序等移动大量元素的操作。
3.选择顺序容器类型的一些准则
1.如果需要随机访问一个容器,则选择vector;
2.若已经知道需要存储元素的数目,则选择vector;
3.若需要随机插入/删除(不仅仅在两端),则选择list;
4.只有需要在首端进行插入/删除操作的时候,还要兼顾随机访问效率,才选择deque,否则都选择vector;
5.若既需要随机插入/删除,又需要随机访问,则需要在vector与list间做个折中-deque;
6.当要存储的是大型负责类对象时,list要优于vector;当然这时候也可以用vector来存储指向对象的指针,同样会取得较高的效率,但是指针的维护非常容易出错,因此不推荐使用