[C++] STL容器设计原理
一、内存映像
容器在概念上是一种可以动态增大或减小的模型,所以其元素在实现上不可能直接保存在容器对象里,而应该保存在自由内存或堆上。这里要区分两个概念“容器对象”和“容器元素对象”。容器本身就是一个C++对象,其大小在运行时是不可以改变,因此容器应该有办法指示其每一个元素在内存中的位置,以便用户能通过容器对象找到其中的元素对象。
二、存储方式和访问方式
向量和链表是两种最基本的动态结构,也是STL中两种最基本的容器,分别对应动态数组和链表结构,同时他们分别代表了内存中同类型批量数据存放的两种基本方式:连续存储和随机存储(不连续存储)。
不同的存储方式决定了不同的访问方式,顺序访问和随机访问。所谓的随机访问是指通过开销恒定的算数运算来得到任一元素的内存地址的访问方法。而顺序访问则是指从第一个元素开始遍历,直到找到所需的元素为止。C++/C的内置数组和vector既可以随机访问也可以顺序访问的容器,而list则只能顺序访问。
只要底层存储机制采取连续存储方式的容器,就可以随机访问其中任一元素,否则只能顺序访问,任何容器都能顺序访问。
三、容器的分类
STL中将容器划分为两类:顺序容器和关联式容器。这里的“顺序”和“关联”指的是上层接口表现出来的访问方式,并非底层存储方式。STL主要采用向量、链表、二叉树和它们的组合作为底层存储结构来实现容器。
链表(list)作为顺序容器的典型代表,其特点是“天然有序”,即各元素之间具有天然的相对位置关系。
集合(set)是关联式容器的典型代表,关联式容器在概念上是无序的,但只计算机上实现这样的数学模型,不但要使上层的访问接口正确反映集合的概念,还要考虑实现效率。因此关联式容器在实现上必须是有序和排序的,只不过对用户透明。平衡二叉搜索树能够满足这些要求。
四、什么样的对象能作为STL的容器元素。
根据上述条件,显然引用不能作为STL容器的元素类型:第一、引用在创建时必须初始化为一个具体的对象,而STL容器不能满足这一要求。二引用没有构造函数和析构函数,更没有赋值语义。STL容器只支持对象语义,而不支持引用语义。例如下面的定义是错误的,
std::list<double&> id(10);
采用接管方式创建和释放不对称的指针对象都不适合作为STL容器的元素,想auto_ptr<>。
参考书:
《高质量程序设计--C/C++描述》