STL及一些容器底层实现机制

Posted 药剂学徒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL及一些容器底层实现机制相关的知识,希望对你有一定的参考价值。

1、vector容器

vector的数据安排以及操作方式,与数组类似。俩这唯一的区别就是空间的运用灵活性。数组是静态空间,一旦配置了就不能改变,vector是动态数组。在堆上分配内存。vector是动态空间,随着元素的加入,它的内部机制会自动扩充空间容纳新的元素当前大小实惠再分配内存,这个大大影响了vector的效率。因此,vector的运用对于内存的合理利用与运用的灵活性有很大的帮助,我们再也不必因为空间不足而已开始要求一个大的数组。

vector动态的增加大小,并不是在元空间之后持续新空间,二十余原大小的两倍另外配置一块较大的空间,然后将原内容拷贝过来,然后才开始在原来的内容之后构造新元素,并释放元空间。因此,对vector的任何操作,一旦因其空间重新配置,同时执行原vector的所有迭代器都失效了。

对最后的元素操作最快,此时一般不需要移动内存对中间的开始处进行添加删除元素操作需要移动内存。如果你的元素使结构或石磊,那么移动的同时还会进行构造和析构的操作,所以性能不高。访问方面,对任何元素的访问都是O(1)也就是常数时间。

总结:vector常用来保存需要经常进行随机访问的内容,并且不需要对中间元素进行添加删除操作。

2、list容器:每次插入或者删除一个元素,就配置或者释放一个元素空间,元素也是在堆中。因此,list对于空间的运用有绝对的精准,一点也不浪费。而且,对于任何位置的元素的插入或元素移除,永远是常数时间。STL中的list底层是一个双向链表,而且是一个环装双向链表。这个特点使得他的随机存取变得非常没有效率,因此,他没有提供[]操作符的重载。

总结:如果添加或者删除大对象的话,使用list;要保存的对象不打,构造与析构操作不复杂可以使用vector代替;

list<指针>完全是性能最低的做法,这种情况还是使用vector<指针>号,因为指针没有构造与析构,也不占用很大内存。

 

3、deque容器

是一种双向开口的连续线性空间,元素也是在堆中。所谓双向开口,意思是可以在对威力A段分别作元素的插入和删除。deque和vector最大差异,一是:deque允许常数时间内对起头端进行元素的插入或移除操作,二在于、deque没有所谓容量观念,因为他是动态地一分段连续空间组合而成,随时可以增加以短信的空间并连接在一起。

deque 是由一段一段的定量连续空间构成。一旦有必要在 deque 的前端或尾端增加新空间,便配置一段定量连续空间,串接在整个 deque 的头端或尾端。deque 的最大任务,便是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机存取的接口。避开了“重新配置,复制,释放”的轮回,代价则是复杂的迭代器架构。因为有分段连续线性空间,就必须有中央控制器,而为了维持整体连续的假象,数据结构的设计及迭代器前进后退等操作都颇为繁琐。

  deque使用一块所谓的map作为主控。这里的map是一小块内存空间,其中每个元素都是指针,指向领一块儿线性空间称为缓冲区。缓冲区才是deque的存储空间主体。

支持[]操作符,也就是支持随即存取,可以在前面快速地添加删除元素,或是在后面快速地添加删除元素,然后还可以有比较高的随机访问速度和vector 的效率相差无几。deque 支持在两端的操作: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。

4、stack:是一种先进后出的存储结构。他只有一个出口,stack允许新增元素,一处元素,取得顶端元素,但是除了最顶端之外没有任何其他方法可以存取stack的其他元素,stack不允许遍历行为。

以某种容器( 一般用 list 或 deque 实现,封闭头部即可,不用 vector 的原因应该是容量大小有限制,扩容耗时)作为底部结构,将其接口改变,使之符合“先进后出”的特性,形成一个 stack,是很容易做到的。deque 是双向开口的数据结构,若以 deque 为底部结构并封闭其头端开口,便轻而易举地形成了一个stack。因此,SGI STL 便以 deque 作为缺省情况下的 stack 底部结构,由于 stack 系以底部容器完成其所有工作,而具有这种“修改某物接口,形成另一种风貌”之性质者,称为 adapter(配接器),因此,STL stack 往往不被归类为 container(容器),而被归类为 container adapter。

5、queue:是一种先进先出的存储结构。有俩个出口,queue允许新增元素,移除元素,从最低端加入元素,取得最顶端元素。但除了最低端可以加入,最顶端可以取出外,没有人其他方法可以存取queue的其他元素。 

6、map和multimap:map的特性是:所有元素都会根据元素的键值自动被排序。map的所有元素都是pair,同时拥有实值value和减值key。pair的第一元素被视为键值,第二元素被视为实值。map不允许俩各元素拥有相同的键值。由于红黑树是一种平衡二叉搜索树,自动排序的效果很不错,所以标准库STLmap就是以红黑树为的层级制。又由于map所开放的各种操作接口,红黑树也都提供了,所以几乎所有map的操作行为,都是红黑树的操作行为。

multimap的特定以及用法与map完全相同,唯一的差别在于他允许键值重复,因此它的插入操作采用的是它的底层机制的insert_equal()而非insert_unique。

以上是关于STL及一些容器底层实现机制的主要内容,如果未能解决你的问题,请参考以下文章

[C/C++ -STL]vector底层实现机制刨析

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

C++ 学习笔记:STL 容器一些底层机制

超详细STL之基于源码剖析vector实现原理及注意事项

超详细STL之基于源码剖析vector实现原理及注意事项

STL的一些技巧函数使用