《STL源码剖析》要点摘抄
1. STL的空间配置器
SGI STL设计了双层级配置器,第一级配置器直接使用malloc()、free(),第二级配置器则视情况采用不同的策略:当配置区块超过128bytes时,视为“足够大”,便调用第一级配置器;当配置区块小于128bytes时,视为“过小”,为降低额外负担,便采用复杂的memory pool整理方式,不再求助于第一级配置器。第二级配置器维护16个自由链表,负责16种小型区块的次配置能力。内存池以malloc()配置而得。如果内存不足,转调用第一级配置器。
设计“内存不足处理例程”是客户端的责任。如果客户端没有设计,则STL直接丢出bad_alloc异常,或利用exit(1)直接退出程序。
当第二级配置器配置区块时,会将要配置的小额区块的内存需求量上调至8的倍数。当发现自由链表(free list)中没有可用区块时,就调用refill(),缺省取得20个新节点。
2. STL的迭代器
迭代器(iterator):扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,迭代器必须实现operator*, operator->, operator++, operator--。因为只有容器设计者知道该如何遍历自己的元素,所以STL并没有将迭代器单独列出来以满足所有的容器。
偏特化(Partial Specialization),意思是如果class template拥有一个以上的template参数,可以针对其中某个(或数个,但非全部)template参数进行特化工作。(另一种解释是针对任何template参数更进一步的条件限制所设计出来的一个特化版本)。
Quick Sort的泛型算法一定要求迭代器是RandomAccessIterators。因为任何一个元素都可以被选作枢轴(pivot),但是其合适与否却会影响Quick Sort的效率。为了避免枢轴不够随机带来的恶化效应,最理想的方式是取整个序列的头、尾、中央三个位置的元素,以其中值作为枢轴,这种做法成为三点中值(Median-of-Three),为了能够快速取出中央位置的元素,显然迭代器必须能够随机定位,因此快速排序的泛型算法中迭代器必须是RandomAccessIterators。
3. 序列式容器
vector维护的是一个连续线性空间(可以理解为数组),支持随机存取,因此提供的迭代器是RandomAccessIterators。增加新元素时,如果超过当时的容量,则容量会扩充至两倍。所谓的动态增加大小,并不是在原空间之后接续新空间,而是以原大小的两倍另外配置一块空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。
list封装了链表。SGI STL的list是一个双向链表(double linked-list),迭代器必须具备前移和后移的能力,所以list提供的是Bidirectional Iterator(注意,list不支持随机存取,所以提供的不是RandomAccessIterators)。list的删除操作只有“指向被删除元素”的那个迭代器失效,其他迭代器不受影响。
list和vector的最主要的区别在于vector使用连续内存存储的,它支持[]运算符,而list是以链表形式实现的,不支持[]。vector对于随机访问的速度很快,但是对于插入尤其是在头部插入元素速度很慢,在尾部插入速度很快。list对于随机访问速度慢得多,因为可能要遍历整个链表才能做到,但是对于插入就快的多了,不需要拷贝和移动数据,只需要改变指针的指向就可以了。另外对于新添加的元素,vector有一套算法,而list可以任意加入。
vector是单向开口的连续线性空间,deque则是一种双向开口的连续线性空间。vector当空间不足时,是另外分配一块空间,拷贝原有内容,删除旧空间;而deque是另外分配一块空间,但是deque的接口提供的还是连续的接口,显然deque内部的迭代器做了很多工作,使得deque至少看起来是连续线性的。
stack是封装的deque,换句话说stack实际上是一种配接器。配接器是对内部物的某些接口的封装,不提供内部物的其他接口的访问,与继承等有明显不同。
4. 关联式容器
map,set属于标准关联容器,使用了非常高效的平衡搜索二叉树:红黑树(RB-tree),它的插入删除效率比其他序列容器高是因为不需要做内存拷贝和内存移动,而直接替换指向节点的指针即可。平衡二叉树有许多种类型,包括AVL-tree、RB-tree等。
二叉搜索树(binary search tree),又称二叉查找树,二叉排序树,可提供对数时间的元素插入和访问。二叉搜索树的节点放置规则是:任何节点的键值一定大于其左子树中每一个节点的键值,并小于其右子树中的每一个节点的键值。因此,从根节点一直往左走,直至无左路可走,即得最小元素;相反,即得最大元素。
注意,二叉搜索树的插入和删除常作为面试题。删除操作分为两种情况,一种是被删除节点只有一个子节点,直接将该子节点替换被删除节点的父节点即可;第二种是被删除节点的左右子节点都在,则将右子树中的最小值替换被删除节点即可。
set自动排序,不能直接修改元素,需要先删除再插入,不能重复,multiset可以。set插入删除元素后,原有的除了被删除节点迭代器的其他迭代器不失效。set之所以不能直接修改元素值,是因为set的元素值就是其键值,关系到set元素的自动排序规则。
map会根据元素的键值自动排序。map的所有元素都是pair,同时拥有键值(key)和实值(value)。pair的第一元素称为键值,第二个元素称为实值。map的键值不允许修改。map不允许两个元素拥有相同的键值。
set和vector的区别在于set不包含重复的数据。set和map的区别在于set只含有key,而map有一个key和key所对应的value两个元素。map和hash_map的区别是hash_map使用了hash算法来加快查找过程,但是需要更多的内存来存放这些hash元素,因此可以算得上是采用空间来换取时间策略。
《STL源码剖析》要点摘抄的更多相关文章
- STL"源码"剖析-重点知识总结
STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...
- 【转载】STL"源码"剖析-重点知识总结
原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...
- (原创滴~)STL源码剖析读书总结1——GP和内存管理
读完侯捷先生的<STL源码剖析>,感觉真如他本人所说的"庖丁解牛,恢恢乎游刃有余",STL底层的实现一览无余,给人一种自己的C++水平又提升了一个level的幻觉,呵呵 ...
- 《STL源码剖析》环境配置
首先,去侯捷网站下载相关文档:http://jjhou.boolan.com/jjwbooks-tass.htm. 这本书采用的是Cygnus C++ 2.91 for windows.下载地址:ht ...
- STL源码剖析读书笔记之vector
STL源码剖析读书笔记之vector 1.vector概述 vector是一种序列式容器,我的理解是vector就像数组.但是数组有一个很大的问题就是当我们分配 一个一定大小的数组的时候,起初也许我们 ...
- STL源码剖析 迭代器(iterator)概念与编程技法(三)
1 STL迭代器原理 1.1 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型,STL设计的精髓在于,把容器(Containers)和算法(Algorithms)分开,而迭代器(i ...
- STL"源码"剖析
STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略 ...
- 《STL源码剖析》相关面试题总结
原文链接:http://www.cnblogs.com/raichen/p/5817158.html 一.STL简介 STL提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
- STL源码剖析之序列式容器
最近由于找工作需要,准备深入学习一下STL源码,我看的是侯捷所著的<STL源码剖析>.之所以看这本书主要是由于我过去曾经接触过一些台湾人,我一直觉得台湾人非常不错(这里不涉及任何政治,仅限 ...
- STL源码剖析 — 空间配置器(allocator)
前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配 ...
随机推荐
- K:线性表的实现—顺序表
所谓顺序表,就是顺序存储的线性表.顺序存储就是用一组地址连续的存储单元依次存放线性表中各个数据元素的存储结构. 线性表中所有数据元素的类型是相同的,所以每一个数据元素在存储器中占用相同的大小的空间.假 ...
- C#学习笔记-原型模式
题目:编写基本的简历. 实现: 创建基本的Resume类,然后主函数通过实例化Resume来写简历即可. Resume类: class Resume { private string name; pr ...
- BZOJ4162:shlw loves matrix II
传送门 利用Cayley-Hamilton定理,用插值法求出特征多项式 \(P(x)\) 然后 \(M^n\equiv M^n(mod~P(x))(mod~P(x))\) 然后就多项式快速幂+取模 最 ...
- bzoj P3884 上帝与集合的正确用法
Description 根据一些书上的记载,上帝的一次失败的创世经历是这样的: 第一天, 上帝创造了一个世界的基本元素,称做“元”. 第二天, 上帝创造了一个新的元素,称作“α”.“α”被定义为“ ...
- RabbitMq、ActiveMq、ZeroMq、kafka各个消息中间件之间的区别
MQ框架非常之多,比较流行的有RabbitMq.ActiveMq.ZeroMq.kafka.这几种MQ到底应该选择哪个?要根据自己项目的业务场景和需求. 第一部分:RabbitMQ,ActiveMq, ...
- Gulp前端服务器本地搭建
前端服务器本地搭建分三阶段: 1.Node.js的安装 2.Npm环境配置 3.编写JS文件 1.Node.js安装: 如图所示: Next: 选择I accept 然后Next: 选择安装文件的位置 ...
- linux下close 掉socket 之后 阻塞的recv 不会立即返回
转载自:http://www.cnblogs.com/wainiwann/p/3942203.html 在开发的一个基于rtmp聊天的程序时发现了一个很奇怪的现象. 在windows下当我们执行 cl ...
- C# 串口
/// <summary> /// 串口初始化 /// </summary> private void OpenSerialPort ...
- UX基础 - OmniGraffle新手指南
原文地址:http://beforweb.com/node/202,大半夜找到,作为使用手册 我发现一事儿,就是最近这些年,每到入职一个新公司的时候,听得东西往往会比多数时候听得更重更金属些,此时以S ...
- 数值的整数次方(C++ 和 Python 实现)
(说明:本博客中的题目.题目详细说明及参考代码均摘自 “何海涛<剑指Offer:名企面试官精讲典型编程题>2012年”) 题目 实现函数 double Power(double base, ...