《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基础
每一个今天的坚持都会改变明天的自己! 一.python介绍 python是一门由解释型.弱类型的高级开发编程语言,由龟叔于1989圣诞开发出,后经过二十多年的发展,因其简洁高效的特点而被广泛使用,在世 ...
- 浅谈ul布局以及table布局
我个人对于某些言论说要注重html语义化在布局中的应用,我反而不怎么感冒,试试兼容IE7&&项目期相对较赶的情况下,我还是推荐快速开发为主,兼容性强为主. 如果布局中需要用户边框,推荐 ...
- Ubuntu16.04 下安装tomcat
有两种常用方法: 一.通过 apt-get 命令进行在线安装(会自动配置好环境变量和服务) 二.通过下载并解压 .tar.gz 包进行手动安装(需要手动配置环境变量) 一.通过 apt-get 命令进 ...
- Linux 安装命令
- LeetCode算法题5----Longest Palindromic Substring
#5. Longest Palindromic Substring Given a string S, find the longest palindromic substring in S. You ...
- MySQL数据库(10)----IN 和 NOT IN 子查询
当子查询要返回多个行来与外层查询进行比较运算时,可以使用运算符 IN 和 NOT IN.它们会测试某个给定的比较值是否存在于某一组值里.如果外层查询里的行与子查询返回的某一个行相匹配,那么 IN 的结 ...
- Android组件化框架项目详解
简介 什么是组件化? 项目发展到一定阶段时,随着需求的增加以及频繁地变更,项目会越来越大,代码变得越来越臃肿,耦合会越来越多,开发效率也会降低,这个时候我们就需要对旧项目进行重构即模块的拆分,官方的说 ...
- Intent和BroadcastReceiver
Intent简介 Intent是一种消息传递机制,作用: 使用类名显示启动一个特定的Service或Activity 启动Activity或Service来执行一个Intent 广播某个事件已经发生 ...
- 如何安装window7 语言包
很多下载的语言包都是.exe文件,双击后生成lp.cab文件. 这时马上把文件复制到另外一个文件夹中,直接拖最快. 这是 window7 sp1 的很多语言包下载地址(企业版和旗舰版通用):http: ...
- C#字节流通信格式
类似通信格式的实现关键点: byte数组转float的实现,BitConvetor.toSingle() float类型转by,BitConverter.GetBytes #客户端发送public b ...