《STL源码解析》读书笔记之allocator(1)

内存配置器allocator是stl中的一个模板类,它提供类型化的内存分配以及释放操作。SGI STL的配置器与众不同,其名称是alloc而非allocator,而且不接受任何参数(如vector<int,std::alloc>)。每个SGI STL容器采用的默认内存配置其都是alloc而不是allocator。

首先介绍allocator。SGI中虽然有allocator的定义,但基本上从不用它,原因是效率不高。它仅仅是把c++的new和delete稍微做了一点封装而已(allocate函数直接采用::operator new实现,deallocate函数直接采用:: operator delete实现,注意和new operaotr与delete operator的区别)。

真正在STL里面运用的多的是alloc类,下面我们来讨论它的实现原理。new操作符实质上可分为两个阶段的操作:(1)调用::opeartor new申请内存。(2)调用对象的构造对象内容。delete操作符实质上也分两个阶段操作:(1)调用对象的析构函数销毁对象。(2)释放对象占用的内存。alloc类在对内存进行管理时,将这两部分操作分离开来。申请内存的操作由alloc::allocate()函数负责,释放内存的操作由alloc::deallocate()负责。对象构造由::construct()负责,对象析构由::destroy()负责。相应的函数和模板类所在的头文件如下图所示:

首先看对象的构造与析构。为了提高效率与保证安全,destroy函数分几种情况处理。destroy函数和construct函数的流程如下图所示:

我们再来看对象内存的申请与释放。对象内存的申请与释放的操作都被定义在<stl_alloc.h>文件中,它要考虑的问题有已下几点:(1)向system heap申请空间。(2)考虑多线程的状态。(3)考虑内存不足时的应变措施。(4)考虑内存碎片的问题。

考虑到可能存在的内存碎片的问题,SGI STL采用了双层级配置器。第一级不管申请的内存多大都直接使用malloc和free申请和释放内存,它是由_malloc_alloc_template类模板实现的;第二级根据申请内存的大小采取相应的操作:当申请的内存大于128byte时,视为申请的内存较大,直接调用第一级申请内存;当申请的内存小于128byte时,视为申请的内存较小,采用内存池(memory pool)的方式申请内存,以防止内存碎片的产生,它是由_default_alloc_template内模板实现的。整个实现是支持双级配置器还是只采用第一级可以通过测试_USE_MALLOC是否被定义来确定。

一二级配置其的关系,接口包装以及实际运用方式见下图:

STL定义有5个全局函数作用与为初始化的空间上。前面已经说了两个了,分别是用于构造的construct和用于析构的destroy。另外三个函数分别是uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n()。它们分别向目标区域拷贝,填充,重复填充n次对象。这三个函数运行时都首先鉴别操作的数据类型是否为POD(pure
old data)类型的数据。POD型别必然拥有trivial ctoc/dtor/copy/assignment函数。如果是POD型的数据,我们可以采取最有效率的初值填写手法(交给高阶的copy,fill,fill_n来处理)。而对于non-POD类型的数据,则采取保险的做法(调用构造函数)。

处理流程概括如下:

时间: 2024-08-03 03:14:02

《STL源码解析》读书笔记之allocator(1)的相关文章

STL 源码剖析读书笔记一:空间配置器

1. STL 的空间配置器 STL 空间配置器在运用的角度来说,是最不需要介绍的,它总是隐藏在一切组件背后.但若以 STL 的实现角度而言,第一个需要理解的就是空间配置器. 根据 STL 规范,以下是 allocator 的必要接口: allocator::value_type allocator::pointer allocator::const_pointer allocator::reference allocator::const_reference allocator::size_ty

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

阅读基础: Foo *pf = new Foo; 执行了两个步骤: 1)::operator new 向系统申请内存. 2) 调用Foo::Foo()构造函数构造实例.  ==> 申请内存,构造实例. delete pf; delete; 执行了两个步骤: 1)调用Foo::~Foo()析构函数. 2). ::operator delete释放内存.         ==> 析构实例,释放内存. Stl Alloc实现: Stl为了高效利用内存,将这两部分分开,分成了四个操作( 构造::con

STL 源码剖析读书笔记三:序列式容器之 vector、list

1. STL 中的容器 容器,置物之所也.STL 容器即是将运用最广的一些数据结构实现出来.如下图所示: 上图以内缩方式来表达基层和衍生层的关系.所谓衍生,并非派生关系,而是内含关系.例如 heap 内含一个 vector,priority-queue 内含一个 heap.stack.queue都内含一个 deque,set/map/multimap/multiset 都内含一个 RB-tree,hash_x 都内含一个 hashtable. 2. 序列式容器之 vector 所谓序列式容器,其

STL 源码剖析读书笔记四:序列式容器之 deque、stack、queue

1. 序列式容器 deque 1.1 deque 概述 vector是单向开口的连续线性空间,用户只能在vector尾部进行插入删除操作,而 deque 是一种双向开口的连续线性空间,允许我们在头尾两端操作. deque 和 vector 的最大差异在于: deque 允许常数时间对头端元素进行插入和移除操作 deque 没有所谓容量(capacity)概念,因为它是动态地以分段连续的空间组合而成,随时可以增加一段新的空间并链接起来 deque提供的迭代器也是 RandomAccess Iter

STL 源码剖析读书笔记二:迭代器与traits

1. 迭代器概述 迭代器是一种抽象的设计概念,现实程序语言中并没有直接对应这个概念的实物.<设计模式>中对于迭代器模式的定义为:提供一种方法,使之能够依序访问某个聚合物所含的各个元素,而又无需暴露该聚合物的内部表述方式. STL 的中心思想在于:将数据容器和算法分开,彼此独立设计,再以迭代器粘合.容器和算法的泛型化在技术角度来看并不困难,C++ 的类模板和函数模板可分别达成目标.如何设计出两者的良好粘合剂,才是大难题. 迭代器是一种类似于指针的对象,而指针的各种行为中最常见也最重要的便是内容提

《STL源码解析》读书笔记之序列式容器(2)

1.deque deque和vector的最大差异在于deque允许在常数时间内对首端进行元素的插入和删除操作.而且deque没有容量的观念,因为它是动态地以分段连续空间组合而成的,随时可以增加一段新的空间并链接起来.像vector那样因旧空间不足而重新配置一块更大空间的情况在deque里是不会发生的.虽然deque也提供Random Access Iterator,但它的迭代器并不是普通指针,这影响了很多操作的效率. (1)deque的map deque在逻辑上是连续空间,但实际上它是由一段一

STL 源码解析

一开始一直无法理解STL中的内存分析,一天很困,翻开了侯捷的STL源码解析,阅读一二,这是一针见血,字字珠玑,解开了一个又一个迷惑~ 简单记录,和大家分享一下 1) 空间适配器 template <class T1,class T2> inline void _construct(T1 *p,const T2 &value) { new (p) T1(value);  // placement new, and allocate object on the requested memo

2015.07.20MapReducer源码解析(笔记)

MapReducer源码解析(笔记) ? 第一步,读取数据源,将每一行内容解析成一个个键值对,每个键值对供map函数定义一次,数据源由FileInputFormat:指定的,程序就能从地址读取记录,读取的记录每一行内容是如何转换成一个个键值对?Mapper函数是如何调用键值对?这是由InputFormatClass完成的,它在我们的例子中的具体实现类是TextInputFormat(Text是普通的文本,log日志,数据库中的数据就不是),总的来说:TextInputFormat把数据源中的数据

STL源码剖析 — 空间配置器(allocator)

前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配置器,配置的对象,是内存.(以下内容来自<STL源码剖析>) 空间配置器的标准接口 根据STL的规范,allocator的必要接口 各种typedef 1 allocator::value_type 2 allocator::pointer 3 allocator::const_pointer 4

stl源码剖析学习笔记(二)traits编程技法简明例程

解释说明 traits侯捷老师的翻译是萃取.其目的就是在编译期进行模板调用的类型识别,从而做一些事情. 最突出的例子,我觉得不是<STL源码剖析>中"迭代器概念与traits编程技法"这一章的说明,而是stl算法中copy的实现.代码在stl源码的stl_algobase.h中. copy的最终实现,大致分为两类,一类是直接整块内存的memmove操作,另一类是一个个对象赋值.其中涉及has_trivial_assignment_operator的类型推断. 如果has_t