n 查找速度是个关键考虑因素吗?如果是,那你需要去看散列容器(hashed container)(见条款25),排序的vectors(见条款23),还有标准关联容器——按此顺序选择。
n 你介意底层容器使用引用计数(reference counting)吗?如果是,那你需要好好驾驭string,这是因为许多string实现是基于引用计数(reference-counted)的(见条款13)。你也要避免使用rope,因为确定的rope实现是基于引用计数的(见条款50)。你必须描绘自己的strings,当然,你应当考虑vector<char>。
n 你需要插入和擦除的事务语义(transactional semantics)吗?就是说,你需要可信赖的回滚(roll back)插入和擦除操作的能力吗?如果是,你需要使用基于节点的容器。如果你需要多元素插入的事务语义(transactional semantics)(例如:区间形式——见条款5),你应当选择list,这是因为list是仅有的提供多元素插入事务语义的标准容器。事务语义(transactional semantics)对有兴趣写异常安全代码的程序员尤其重要。(事务语义(transactional semantics)也可以用连续内存容器达到,但是会有性能代价,代码也不简单。要了解更多,请看Sutter’s Exceptional C++[8]的条款17。)(译注:Exceptional C++已经由电力出版社出版中文版。)
n 你需要使iterator,pointer以及reference的失效最少化吗?如果是,你应当使用基于节点的容器,因为在这些容器中插入和擦除永远不会使iterators,pointers或references失效(除非它们指向你正在擦除的元素)。一般来讲,在连续内存容器上插入或擦除可能导致容器内任何存在的iterators, pointers以及references失效。
n 有这样一种序列式容器,它的迭代器类型是random access iterator,只要没有擦除操作发生并且总是在容器的尾部插入新元素,(迭代器中)指向数据的指针和引用不会失效,拥有这样的容器有帮助吗?这是一种非常特殊的情况,但是如果这是你的情况,deque就是你梦想中的容器。(有趣的是,当在deque的尾部插入元素时其迭代器可能会失效。deque是仅有的迭代器可能会失效而指针和引用却不会失效的标准STL容器。)
这些问题几乎不可能是所有事情的结束。例如,它们没有考虑不同容器类型所采用的各种各样的内存分配策略。(条款10和条款14讨论了这些策略的某些方面。)还有,除非你对元素排序,标准一致性,迭代器兼容,与C的布局兼容,查找速度,由于引用计数而导致的行为不规则,事务语义的轻松实现,或迭代器失效的条件没兴趣,它们应当足够使你确信,你并不仅仅只要考虑容器操作的算法复杂性,而是比这多的多。当然,这种复杂性很重要,但它只是所有问题中的一小部分。
在容器方面,STL给了你许多选择。如果你不局限于STL,甚至有更多的选择。在选择一种容器之前,确保考虑了所有的选择。“缺省容器”吗?我不认为是这样。