(原创滴~)STL源码剖析读书总结1——GP和内存管理
读完侯捷先生的《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和内存管理的更多相关文章
- STL源码剖析读书笔记之vector
STL源码剖析读书笔记之vector 1.vector概述 vector是一种序列式容器,我的理解是vector就像数组.但是数组有一个很大的问题就是当我们分配 一个一定大小的数组的时候,起初也许我们 ...
- STL源码剖析读书笔记--第四章--序列式容器
1.什么是序列式容器?什么是关联式容器? 书上给出的解释是,序列式容器中的元素是可序的(可理解为可以按序索引,不管这个索引是像数组一样的随机索引,还是像链表一样的顺序索引),但是元素值在索引顺序的方向 ...
- Stl源码剖析读书笔记之Alloc细节
阅读基础: Foo *pf = new Foo; 执行了两个步骤: 1)::operator new 向系统申请内存. 2) 调用Foo::Foo()构造函数构造实例. ==> 申请内存,构造 ...
- STL源码剖析读书笔记--第6章&第7章--算法与仿函数
老实说,这两章内容还蛮多的,但是其实在应用中一点点了解比较好.所以我决定这两张在以后使用过程中零零散散地总结,这个时候就说些基本概念好了.实际上,这两个STL组件都及其重要,我不详述一方面是自己偷懒, ...
- 《STL源码剖析》读书笔记
转载:https://www.cnblogs.com/xiaoyi115/p/3721922.html 直接逼入正题. Standard Template Library简称STL.STL可分为容器( ...
- 通读《STL源码剖析》之后的一点读书笔记
直接逼入正题. Standard Template Library简称STL.STL可分为容器(containers).迭代器(iterators).空间配置器(allocator).配接器(adap ...
- STL源码分析读书笔记--第二章--空间配置器(allocator)
声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...
- STL"源码"剖析-重点知识总结
STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...
- 【转载】STL"源码"剖析-重点知识总结
原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...
随机推荐
- Constants in C++
The first motivation for const seems to have been to eliminate the use of preprocessor #define for v ...
- ubuntu tengine 安装
参考文章:http://wangyan.org/blog/install-openssl-from-source.html http://www1.site90.com/Linux/405.html ...
- C# WinForm给Button按钮或其它控件添加快捷键响应
就在这介绍三种添加快捷键的方式. 第一种Alt + *(按钮快捷键) 在大家给button.label.menuStrip等控件设置Text属性时在名字后边加&键名就可以了,比如button1 ...
- 再看JavaScript线程
继上篇讨论了一些关于JavaScript线程的知识,我们不妨回过头再看看,是不是JavaScript就不能多线程呢?看下面一段很简单的代码(演示用,没考虑兼容问题): 代码判断一: <div i ...
- c++模板实例化的一个例子
以下是c++模板实例化的一个例子,虽然ObjectList::clear()里面调用的test()函数是没有定义的,但是以下代码能够编译通过,可见ObjectList::clear()未编译: tem ...
- Apache配置允许文件索引
这两天在看bootstrap的文档,所以在本地搭建了一个web server. 这里记下Apache的一个小配置: LISTEN *:8000 <VirtualHost *:8000> A ...
- Swift(三.函数)
一.swift中的函数分为以下几类吧 1>无参无返 2>无参有返 3>有参无返 4>有参有返 5>有参多返 二.看下面几个例子吧 1>无参无返 func a ...
- Java笔记1 : 在生产者消费者模式中,线程通信与共享数据,死锁问题与解决办法
本例定义了4个类,这里说一下,方便下面讲解.分别是Product(产品),Producer(生产者),Consumer(消费者), Test(测试类). 多线程之间通信与共享数据只要引用同一内存区域就 ...
- 理解Python的迭代器
首先,廖雪峰老师的教程中解释了迭代器和生成器,这篇文章只是补充和我个人的总结. 什么是迭代 可以直接作用于for循环的对象统称为可迭代对象(Iterable). 可以被next()函数调用并不断返回下 ...
- 【技术贴】jsp出现getOutputStream() has already been calle
此错误经常在websphere6.x版本里出现:原因是jsp文件中的尖括号百分号里面有空行或者其他的什么原因,Servlet1.2规范规定了OutputStream只能获得一次,在jsp中实际上已经通 ...



