STL高效编程(-) STL的容器

来源:互联网 发布:电视直播软件 央视 编辑:程序博客网 时间:2024/04/29 18:32

STL有很多概念,迭代器,高效的算法,函数对象,但是对于大多数的开发者而言,STL最突出的地方还是容器(Container),容器远远比数组强大和灵活。

 

容器可以动态增长,独立管理内存,提供对容器元素的高效的灵活的访问,等等。STL容器是有效的封装最常见的数据结构和算法,在我看来,STL容器就是代表着c++的数据结构,从数组,链表,栈,队列,表,哈希表。每一个容器代表着一种数据结构。

 

概括一下,STL的容器可以分为以下几个大类:

一:序列容器, 有vector, list, deque, string.

二 : 关联容器,     有set, multiset, map, mulmap, hash_set, hash_map, hash_multiset, hash_multimap

                                 带有下划线的是非标准的,如果是VC8.0的话,在stdext名字空间里。


三: 其他的杂项: stack, queue, valarray, bitset

 

由此可见,STL为我们提供了那么多的容器,如果想要有效的使用它们,你真的需要弄明白每个容器是干什么的。最好你能知道他们的一些实现原理,陆续的我还会写一些STL容器实现的文章。容器的实现往往决定着你如何更好的使用容器。下面简单讲一下STL各个容器的实现:

1. vector: 内部实现是数组,一段连续的内存。

2. list, 内部实现是双链表

3. deque 内部实现是内存块的链表。

4. string: 连续的内存

5. set,map: 红黑树(平衡二叉树的一种)

6. hash_map, hash_set 用哈希表(散列表)来实现。

7. stack: 用vector或者是deque来实现

8. queue,用deque实现

 

本文仅当时抛砖引玉,大致讲一下选择容器的一些原则。

1. 你需要“可以在容器的任意位置插入一个新元素”的能力吗?如果是,你需要序列容器,关联容器做不到。

 

2. 你关心元素在容器中的顺序吗?如果不,散列容器就是可行的选择。否则,你要避免使用散列容器。

 

3. 必须使用标准C++中的容器吗?如果是,就可以除去散列容器、slist和rope。

 

4. 你需要哪一类迭代器?如果必须是随机访问迭代器,在技术上你就只能限于vector、deque和string,但

你也可能会考虑rope.

 

5. 当插入或者删除数据时,是否非常在意容器内现有元素的移动?如果是,你就必须放弃连续内存容器

 

6. 容器中的数据的内存布局需要兼容C吗?如果是,你就只能用vector.

 

7. 查找速度很重要吗?如果是,你就应该看看散列容器,排序的vector和

标准的关联容器——仅供参考。

 

● 你介意如果容器的底层使用了引用计数吗?如果是,你就得避开string,因为很多string的实现是用引

用计数。于是你得重新审核你的string,你可以考虑使用vector<char>。

 

● 你需要插入和删除的事务性语义吗?也就是说,你需要有可靠地回退插入和删除的能力吗?如果是,

你就需要使用基于节点的容器。如果你需要多元素插入的事务性语义,你就应该选择list,因为list是唯一

提供多元素插入事务性语义的标准容器。事务性语义对于有兴趣写异常安全代码的程序员来说非常重要。

(事务性语义也可以在连续内存容器上实现,但会有一个性能开销,而且代码不那么直观。要了解这方

面的知识,请参考Sutter的《Exceptional C++》。

 

● 你要把迭代器、指针和引用的失效次数减到最少吗?如果是,你就应该使用基于节点的容器,因为在

这些容器上进行插入和删除不会使迭代器、指针和引用失效(除非它们指向你删除的元素)。一般来

说,在连续内存容器上插入和删除会使所有指向容器的迭代器、指针和引用失效。

 

● 你需要具有有以下特性的序列容器吗:1)可以使用随机访问迭代器;2)只要没有删除而且插入只发

生在容器结尾,指针和引用的数据就不会失效?  这个一个非常特殊的情况,但如果你遇到这种情况,

deque就是你梦想的容器。(有趣的是,当插入只在容器结尾时,deque的迭代器也可能会失效,deque

是唯一一个“在迭代器失效时不会使它的指针和引用失效”的标准STL容器。为什么呢?这是由实现所决定的,

以后我会专门写一篇文章来介绍原因。

 

 

更多内容,请参照<effective stl>.

本文仅供学习。转载请注明出处。