Effective STL 第1条:慎重选择容器类型

C++提供了几种不同的容器供我们选择,这里简单回顾一下:

1、标准STL序列容器:vector、string、deque和list。

2、标准STL关联容器:set、multiset、map、和multimap。

3、非标准序列容器slist和rope。slist是一个单向链表,rope本质上是一“重型”string。

4、非标准关联容器hash_set、hash_multiset、hash_map和hash_multimap。

5、vector<char>作为string的替代。

6、vector作为标准关联容器的替代。

7、几种标准的非STL容器,包括数组、bitset、valarry、stack、queue和priority_queue.

 

稍后我们将讨论与算法复杂性相对应得有关容器的重要问题。这里首先引入对STL容器的一种分类方法,也就是对连续内存容器(contiguous-memorycontainer)和基于节点的容器(node-based container)的区分。

连续内存容器(或称为基于数组的容器,array-based container)把它的元素存放在一块或多块(动态分配的)内存中,每块内存中存有多个元素。当有新元素插入或已有的元素被删除时,同一内存块中的其他元素要向前或向后移动,以便为新元素让出空间,或者填充被删除元素所留下的空隙。这种移动影响到效率和异常安全性。标准的连续内存容器有vector、string和deque。非标准的rope也是一个连续内存容器。

基于节点的容器在每一个(动态分配的)内存中只存放一个元素。容器中元素的插入或删除只影响到指向节点的指针,而不影响节点本身的内容,所以当有插入或删除操作时,元素的值不需要移动。表示链表的容器,如list和slist,是基于节点的。所有标准的关联容器也是如此(通常的实现方式为平衡树)。非标准的散列容器使用不同的基于节点的实现。

有了上面的术语作为基础,下面将概括出选择容器时最重要的一些问题。

你是否需要在容器的任意位置插入新元素?如果需要,就选择序列容器;关联容器是不行的。

你是否关心容器中的元素是排序的?如果不关心,则散列容器是一个可行的选择方案;否则,你要避免散列容器。

你选择的容器必须是标准C++的一部分吗?如果必须是,就排除了散列的容器,slist和rope。

你需要哪种类型的迭代器?如果它们必须是随机访问迭代器,则对容器的选择就被限定为vector、deque和string。或许你也可以考虑一下rope。如果要求使用双向迭代器,那么你要避免slist。

当发生元素的插入或删除操作时,避免移动容器中原来的元素是否很重要?如果是,就要避免连续内存容器。

容器中数据的布局是否需要和C兼容?如果需要兼容,就要只能选择vector。

元素的查找速度是否是关键的考虑因素?如果是,就要散列容器、排序的vector和标准关联容器——或许这就是优先顺序。

如果容器内部使用了引用计数技术(reference counting),你是否介意?如果是,就要避免使用string,因为许多string的实现都使用了引用计数。Rope也要避免,因为权威的rope实现是基于引用计数的。当然,你需要某种表示字符串的方法,这时你可以考虑vector<char>。

对插入和删除操作,你需要事务语义(transaction semantics)吗?也就是说,在插入和删除操作失败时,你需要回滚的能力吗?如果需要,你就要使用基于节点的容器。如果对多个元素的插入操作(即针对一个区间的形式)需要事务,则你需要选择list,因为在标准容器中,只有list对多个元素的插入操作提供了事务语义。对那些希望编写异常安全(exception-safe)代码的程序员,事务语义显得尤为重要。(使用连续内存的容器也可以获得事务语义,但是要付出性能上的代价,而且代码也显得不那么直截了当。

你需要使迭代器、指针和引用变为无效的次数最少吗?如果是这样,就要使用基于节点的容器,因为对这类容器的插入和删除操作从来不会使迭代器、指针和引用变为无效(除非他们指向了一个你正在删除的元素)。而针对连续内存容器的插入和删除操作一般会使指向该容器的迭代器、指针、和引用变为无效。

如果序列容器的迭代器是随机访问类型,而且只要没有删除操作发生,且插入操作只发生在容器的末尾,则指向数据的指针和引用就不会变为无效这样的容器是否对你有帮助吗?这是非常特殊的情形,但如果你面对的情形正是如此,则deque是你所希望的容器。(有意思的是,当插入操作仅在容器的末尾发生时,deque的迭代器有可能会变为无效。deque是唯一的、迭代器可能会变为无效,而指针和引用不会变为无效的STL标准容器。)

时间: 2024-10-19 22:48:12

Effective STL 第1条:慎重选择容器类型的相关文章

Effective STL 第7条:如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉

STL中的容器相当"聪明",它们提供了迭代器,以便进行向后和向前的遍历(通过begin.end.rbegin等):它们告诉你所包含的元素类型(通过它们的value_type类型定义):在插入和删除的过程中,它们自己进行必要的内存管理:它们报告自己有多少对象,最多能容纳多少对象(分别通过size和max_size):当然,当它们自身被析构时,它们自动析构所包含的每个对象. 有了这么"聪明"的容器,许多程序员不再考虑自己做善后清理工作.更糟糕的是,他们认为,容器会考虑为

条目1《慎重选择容器类型》

条目一主要是先抛出选择STL容器时面对的问题,并且从中简单的对各个容器做个分类和使用对比. 在选择stl容器类型的时候,一般需要从以下的角度来考虑选择对象: 1.元素的排序情况 2.是否与标准相符 3.迭代器的能力 4.元素布局与C的兼容性 5.查找速度 6.因引用计数数所引起的反常行为 7.是否便于实现事务语义 8.迭代器在何种条件下变为无效 9.算法复杂度 除了标准和非标准容器分类外,不引起人关注的分类方法有根据容器在内存中的存储方式是否连续来分类.基于连续内存的有string,vector

Effective STL 条款1:仔细选择你的容器

条款1:仔细选择你的容器 了解各种容器的实现方法,知道各种容器的内存管理方式.各种操作所对应的底层操作,然后根据需要选择恰当的容器. 对于容器的分类: 标准STL序列容器:vector,string,deque和list 标准STL关联容器:set,multiset,map和multimap 非标准序列容器:slist(单向链表)和rope(重型字符串--不懂) 非标准关联容器:hash_set,hash_multiset,hush_map和hash_multimap vector == str

Effective STL -- 容器

01.慎重选择容器类型 选择容器原则:需要考虑元素的排序情况,是否与标准相符,迭代器能力,元素布局,与C的兼容性,查找速度,引用计数,插入删除对事物语义的支持,某些操作是否会使迭代器无效,内存分配策略. vector 需要使用随机迭代器 容器中布局需要与C兼容 deque 需要使用随机迭代器 当大多数插入在头部和尾部时 在尾部插入不会是迭代器,指针,引用变为无效 string 需要使用随机迭代器 介意使用引用计数计数,避免使用string,rope.string不可行 介意在容器上使用swap导

STL中慎重选择删除元素的方法

 一.要删除容器中有特定值的所有对象 1.如果容器是vector.string或deque,则使用erase-remove习惯用法.例如: vector<int> c; c.erase(remove(c.begin(),c.end(),1963),c.end());//删除值是1963的元素 下面讲一下算法remove: template<classForwardIterator,class T> ForwardIteratorremove(ForwardIterator fi

迅速读懂:Effective STL (五)

这是<Effective STL>笔记最后一期,不能涵盖全部内容,书后仍然有些附加内容,不在附加,有兴趣可以找原书来读读,一则是区域设置后的忽略大小写比较,另一则是MSVC4-5编译器下STL注意事项 条款41:了解使用ptr_fun.mem_fun和mem_fun_ref的原因 函数和函数对象总使用用于非成员函数的语法形式调用.mem_fun带有一个到成员函数的指针,pmf,并返回一个mem_fun_t类型的对象.这是一个仿函数类,容纳成员函数指针并提供一个operator(),它调用指向在

Effective STL 中文版(大全)

Effective STL 中文版(大全) 作者:winter 候捷说,对于STL,程序员有三个境界,开始是使用STL,然后是理解STL,最后是补充STL.Effective STL是一本非常好的书,帮助你更好的理解STL,其作者就是<Effective C++>一书的作者.如果你已经初步了解了STL的容器.迭代器.算法和函数,而又想更好的了解STL,那么<Effective STL>是你的最佳选择. 还有一部分没有找到链接,如果再找不到我会自己试着翻译一下:) 前言 容器 条款1

慎重选择删除元素的方法

总结本条款,一共有以下几点是需要牢记的: 1.要删除容器中有特定值的所有对象: (1).如果容器是vector.string或deque,则使用erase-remove习惯用法. (2).如果容器是list,则使用list::remove (3).如果容器是标准关联容器,则使用它的erase成员函数. eg:  假定你有一个标注的STL容器c,它包含int类型的整数:Container<int> c; 而你想删除c中所有值为1963的元素.则可以使用erase-remove.习惯用法: c.e

STL(标准模板库)理论基础,容器,迭代器,算法

基本概念 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.现然主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间. STL的从广义上讲分为三类:algorithm(算法).container(容器)和iterator(迭代器),容器和算法通过迭代器可以进行无缝地连接.几乎所有的代码都采 用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会.在C++标准中,STL被组织为下面的13