读完侯捷先生的《STL源码剖析》,感觉真如他本人所说的“庖丁解牛,恢恢乎游刃有余”,STL底层的实现一览无余,给人一种自己的C++水平又提升了一个level的幻觉,呵呵~

纵观全书,讲得最多、最透彻的就是C++的Generic Programming的思想。STL通过class template,function template将容器、迭代器、算法从数据类型中解脱出来,使其能“以不变应万变”,并能针对不同数据类型的相关特性(type_traits),从各种版本的实现中选最优而用之,从具体到抽象,又兼具具体特性的考虑,实乃智慧的结晶。这本书也开阔了我的眼界,使我见识了如partial specialization(偏特化),Specialization and Generalization,以偏特化的方式使C++具备type of的能力等的语言运用的现象。下面就先来讲一下class template partial specialization(类模板偏特化):

  • 1. 偏特化

所谓偏特化就是我们在设计class template的时候,除了提供必要的一般化设计之外,还设计了其它比较特殊的版本(比如接受T*为参数等等)。这些版本跟一般化的版本相比,要特殊一些,但有没有丢失什么类型都要的一般性,所以称之为部分特殊化或者偏特化。我们在实例化一个class template的时候,C++会根据传入的template参数类型,自动选取匹配程度最高的template进行实例化,举个栗子:

// 一般化设计

template <class I, class O>

struct testClass

{

testClass() { cout << "I, O" << endl; }

};

// 偏特化版本1

template <class T>

struct testClass< T*, T*>

{

testClass() { cout << "T*, T* " << endl; }

};

// 偏特化版本2

template <class T>

struct testClass<const T*, T*>

{

testClass() { cout << "const T*, T* "<<endl; }

};

int main()

{

testClass<int, char> obj1; // I, O

testClass<int*, int*> obj2; // T*, T*

testClass<const int*, int*> obj3; // const T*, T*

}

  • 2. STL的内存管理

STL的容器要装元素,必须要有空间,而空间从哪里来,从空间配置器allocator中来。

为了减少内存碎片的产生以及提高效率,STL采用两级的空间配置器。有图有真相:

其中,如果需求区块大于128 bytes,则用的是第一级配置器;否则使用第二级配置器,STL一般都默认使用第二级配置器。

先讲第一级配置器:

STL中分配内存和初始化对象时分开进行的。对象的构造construct()比较简单,直接用placement new(用于在已经分配好的空间中构造对象),调用该类型的构造函数就好了。而析构destroy()因为涉及到该类型是不是含trivial destructor,因而有些小复杂。所谓trivial destructor就是那些无关痛痒的dtor(例如,函数体为空),当我们知道含有trivial dtor,我们在析构的时候就可以不调用那些trivial dtors(因为无关痛痒嘛~),从而降低函数调用的成本。相反,若不含trivial dtors(例如涉及到new-delete的动态内存分配),我们在析构的时候就要老老实实调用dtor,否则会memory leak哦~废话少说,上图:

第一级配置器用到了一个内存不足处理例程,即当遇到内存不足,无法分配的时候,就调用这个处理例程。这个处理例程可能会释放一些内存,然后继续尝试分配。这个类似于C++的new-handler机制。

然后是第二级配置器。第二级配置器采用一个freelists的自由链表来管理空闲的区块,有16条不同大小的区块链表,大小从8,16,24...到128 bytes。目的是避免太多的小区快造成内存碎片,同时减少配置时的overhead。例如cookie(你在new一个对象的空间时,系统可能会分配比sizeof(你的对象)略大的内存空间,多出了空间用来记录内存大小,这样delete []p的时候就知道该free多少内存空间了~)。使用第二级配置器分配空间时,如果能从freelists中找到满足需求的最小区块,则从freelists中拨一个区块出去,在deallocate的时候再回收这个区块。当freelists中所需大小的区块已经一个不剩了(该大小的区块链表为null),则调用refill,从memory pool(内存池)中获取一整块大内存,再切分为所需大小的区块,链接到该链表,为该大小的区块“补仓”。如果memory pool也“没货”了,则唯有向heap要了。如果heap有,则向memory pool“注水”;如果heap也没有,则会调用第一级配置器,那里有个内存不足处理例程,实在不行会抛出个exception什么的。再见图:

另外,除了construct()和destroy()以外,还有三个有用的作用于未初始化内存的函数:

好了,今天先讲这么多,碎觉去~~~

(原创滴~)STL源码剖析读书总结1——GP和内存管理的更多相关文章

  1. STL源码剖析读书笔记之vector

    STL源码剖析读书笔记之vector 1.vector概述 vector是一种序列式容器,我的理解是vector就像数组.但是数组有一个很大的问题就是当我们分配 一个一定大小的数组的时候,起初也许我们 ...

  2. STL源码剖析读书笔记--第四章--序列式容器

    1.什么是序列式容器?什么是关联式容器? 书上给出的解释是,序列式容器中的元素是可序的(可理解为可以按序索引,不管这个索引是像数组一样的随机索引,还是像链表一样的顺序索引),但是元素值在索引顺序的方向 ...

  3. Stl源码剖析读书笔记之Alloc细节

    阅读基础: Foo *pf = new Foo; 执行了两个步骤: 1)::operator new 向系统申请内存. 2) 调用Foo::Foo()构造函数构造实例.  ==> 申请内存,构造 ...

  4. STL源码剖析读书笔记--第6章&第7章--算法与仿函数

    老实说,这两章内容还蛮多的,但是其实在应用中一点点了解比较好.所以我决定这两张在以后使用过程中零零散散地总结,这个时候就说些基本概念好了.实际上,这两个STL组件都及其重要,我不详述一方面是自己偷懒, ...

  5. 《STL源码剖析》读书笔记

    转载:https://www.cnblogs.com/xiaoyi115/p/3721922.html 直接逼入正题. Standard Template Library简称STL.STL可分为容器( ...

  6. 通读《STL源码剖析》之后的一点读书笔记

    直接逼入正题. Standard Template Library简称STL.STL可分为容器(containers).迭代器(iterators).空间配置器(allocator).配接器(adap ...

  7. STL源码分析读书笔记--第二章--空间配置器(allocator)

    声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...

  8. STL"源码"剖析-重点知识总结

    STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...

  9. 【转载】STL"源码"剖析-重点知识总结

    原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...

随机推荐

  1. 加载jar文件输出class和method

    package file import java.util.jar.JarEntry import java.util.jar.JarFile import org.junit.Test; class ...

  2. linux管道学习(一)

    最近学习了管道 pipe,在这里进行一下总结. 这里贴一段自己的实做代码 struct node{ int a; long b; }; int main() { ]; pid_t pid; ]; in ...

  3. caffe源码阅读(3)-Datalayer

    DataLayer是把数据从文件导入到网络的层,从网络定义prototxt文件可以看一下数据层定义 layer { name: "data" type: "Data&qu ...

  4. RSA安全性问题

    加密:C=Me(mod n) 解密:M=Cd(mod n) 安全性基础: 穷举法攻击: 1.攻击者设计一个M,C=Me(mod n) 2.d的个数至多有n-1个,尝试使用每个d破解,如果M’=Cd‘( ...

  5. 24种设计模式--责任链模式【Chain ofResponsibility Pattern】

    中国古代对妇女制定了“三从四德”的道德规范,“三从”是指“未嫁从父.既嫁从夫.夫死从子”,也就是说一个女性,在没有结婚的时候要听从于父亲,结了婚后听从于丈夫,丈夫死了还要听儿子的,举个例子来说,一个女 ...

  6. windows phone 8 设置锁屏背景

    本来想研究一下 利用闪光灯实现手电筒的代码,发现不是简答设置FlashMode属性可以解决问题的,ms也没有提供api,无意瞄了一眼侧边栏的文章列表,发现了设置屏幕锁屏背景的实现,手一抖点进去了.还算 ...

  7. 【DP_背包专题】 背包九讲

    这段时间看了<背包九讲>,在HUST VJUDGE上找到了一个题单,挑选了其中16道题集中做了下,选题全部是HDU上的题,大多是简单题.目前做了点小总结,大概提了下每道题的思路重点部分,希 ...

  8. (WinForm)FormBorderStyle属性

    此属性就是获取或设置窗体的边框样式,默认值为 FormBorderStyle.Sizable.共7个值. 属性 意义 None 无边框 FixedSingle 固定的单行边框 Fixed3D 固定的三 ...

  9. 『奇葩问题集锦』Zepto 页面唤醒拨号功能点透

    不废话直接上代码: HTML: <a class="js-tel tel" data-tel="1312414"></a> JS: // ...

  10. Python的面向对象3

    接下来,我们接着讲Python的面向对象,在上一次的博客中,我们详细介绍了类与对象的属性,今天,我们来详细介绍一下面向对象中的方法! 1.定义实例方法 一个实例的私有属性就是以__开头的属性,无法被外 ...