《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提供的配 ...
随机推荐
- python gif动态图的合成
1.确保imageio已经安装 pip install imageio 2.函数准备 def create_gif(image_list, gif_name): import imageio fram ...
- POJ P2104 K-th Number
You are working for Macrohard company in data structures department. After failing your previous tas ...
- CSS 伪类(下)结构性伪类\UI伪类\动态伪类和其他伪类 valid check enable child required link visit
伪类选择器汇总伪类选择器有4种, 结构性伪类\UI伪类\动态伪类和其他伪类. 具体如下 结构性伪类选择器结构性伪类选择器它能够根据元素在文档中的位置选择元素, 这类元素都有个前缀":&q ...
- chrome:插件、跨域、调试....
chrome 调试小技巧 ctrl+shift+c 打开chrome的控制台选中一个元素,然后在控制台输入$0即可获取选中的元素,就可以对其进行操作了. $0.addEventListener(... ...
- template 的使用
插件介绍:template 是一个高性能的JavaScript模板引擎. 插件特性: 1.性能卓越,执行速度快(mustache 与 tmpl 的20多倍): 2.支持运行时调试,可精准定位异常模板所 ...
- Spring Data MongoDB 环境搭建
一.开发环境 spring版本:4.0.6.RELEASE spring-data-mongodb版本:1.4.1.RELEASE junit版本 4.11 maven版本:3.0.5 二.pom.x ...
- MUI框架-06-静态页制作(图片轮播)
MUI框架-06-静态页制作(图片轮播) 轮播也是静态,是相对页面交互来说 上一篇介绍了如何设计一个简单的界面,还没有接触过,请先查看: MUI框架-01-介绍-创建项目-简单页面 轮播组件 之前也介 ...
- 基于Vue的WebApp项目开发(三)
实现根组件通用的头部和底部样式 明白由webpack搭建起来的Vue项目的执行流程,那么就可以知道实现这个需要只要在根组件和入口文件上做“手脚”即可 <!--以后项目的根组件--> < ...
- Anjular中的路由配置以及服务等模块的一些基本操作
1.路由的配置: 在Angular.js中,我们可以根据自己的需求来配置路由,以达到当url中的地址改变时,会跳转不同的页面 <script> //一开始的url:"http:/ ...
- java字节码文件指令集
网上找的没有指令码这列 自己把它加上 更方便查阅 指令从0x00-0xc9 没有0xba 常量入栈指令 指令码 操作码(助记符) 操作数 描述(栈指操作数栈) 0x01 aconst_null nu ...