读完侯捷先生的《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. Android WebRTC视频旋转问题

    最近在对接WebRTC到安卓手机上,有个需求就是手机横屏时将对方图像进行旋转,研究了WebRTC video_render的代码后发现远端的视频渲染使用opengles20或surfaceview实现 ...

  2. svn强制添加注释脚本

    @echo off setlocal set SVN_BINDIR=C:/Program Files/VisualSVN Server/bin/ set REPOS=%1 set TXN=%2 rem ...

  3. Linux grep和find的区别

    这是两个不同的命令,关于grep:Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expressi ...

  4. Web模板引擎本质前奏

    执行字符串表示的函数,并为该函数提供全局变量: #! /usr/bin/env python3 namespace = {'name': 'zingp', 'data': [16, 19, 25]} ...

  5. IP工具类——IpAddress.java

    根据IP地址获取详细的地域信息,也可通过 http://whois.pconline.com.cn/ 获取地址信息. 源码如下:(点击下载  IpAddress.java) import java.i ...

  6. python中self.__class__

    1. python中的self python中的self就相当于C++中的this指针也就是指向对象本身的指针self.name = name 就是当前对象的成员变量name赋值为name. 2.py ...

  7. python中enumerate的使用

    在python的应用中,当我们使用一个数组或者列表的时候既要遍历索引又要遍历元素的时候通常的做法是这样的: >>> lsi = [1,2,3,4,5,6,7,8,9] >> ...

  8. bzoj 3328: PYXFIB 数论

    3328: PYXFIB Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 130  Solved: 41[Submit][Status][Discuss ...

  9. [BZOJ 3530] [Sdoi2014] 数数 【AC自动机+DP】

    题目链接:BZOJ - 3530 题目分析 明显是 AC自动机+DP,外加数位统计. WZY 神犇出的良心省选题,然而去年我太弱..比现在还要弱得多.. 其实现在做这道题,我自己也没想出完整解法.. ...

  10. Mysql Partition 理论知识总结

    简述: 本文内容主要 Giuseppe Maxia 曾在Mysql Conference & Expo 2010发表关于 <Mysql Partition in Mysql 5.1 &a ...