C++标准库——STL之空间配置器

声明:源码同《STL源码剖析》(侯捷)

STL:

  C++标准的模板库,通用性高。

  常见的数据结构封装。

  提供常用的通用算法。

STL六大组件:

  容器      算法       迭代器       仿函数(函数对象)     适配器      配置器

空间配置器的作用:

  1.提高代码复用率,功能模块化。

  2.减少内存碎片问题。

    比如我们list是链式结构,如果其中的成员是一个个new出来的,我们知道new的底层实现是malloc,同时也必须清楚,当malloc一块40字节空间时,操作系统为了能方便找到这块空间还会加一个结构在在这块空间中,所以开辟的空间不止40字节(应该是40+36,vs2013下)。空间利用率低。

  3.效率问题:频率的分配小块内存,效率比较低。

  4.容易造成内存泄漏。

    统一管理更加方便。

  5.调用malloc/new向系统分配的每块内存都有一些额外开销。

  6.空间不足时的应对措施也合理。

    一级空间配置器源码底层有一个__malloc_alloc_template模板类,里面封装了一些函数以应对空间不足的情况。

 

  7.解决部分存在线程安全的问题

  I.最初空间配置器的内部其实就是封装重载了new运算符。

  底层源码框架制定死了,所以只能通过它给的接口调用相关函数。

  比如allocate()函数就是用于分配内存空间,就是写死的,你只能用它。

  II.处理内存碎片的问题时所用的是二级空间配置器。利用内存池的概念。

  当使用空间配置器时有以下过程:

  1.源码中存在一个枚举变量__MAX_BYTES(128)来区分大内存块和小内存块,凡是大于__MAX_BYTES的内存块都是属于一级空间配置器的管理范畴。

  2.二级空间配置器的底层是由一个free list(哈希桶)来管理的。有一个枚举变量__ALIGN的值(8)就是表示哈希桶划分的间隔。

  3.二级空间配置器中会有对应算法来计算出最合适的内存块和内存块个数,然后查询哈希桶是否有对应的内存块或者说内存块是否足够,如果没有,向系统询问调整free list。

    

    如何调用?——refill()函数。

  4.在allocate()函数调用时发现free list中没有空间是,便会呼叫refill()函数重新填充free list。——去找内存池要。

    

    新的空间来自哪?——内存池。这部分工作交给chunk_alloc()。当然也有可能内存池(memory pool)中内存也满足不了要求。

    类中利用两个静态指针 start_free 和 end_free来标识内存池。

    chunk_alloc()会利用end_free - start_free来计算判断内存池的内存量:

      如果存在内存但是不够,就先把能给的给出去。

      如果存在内存而且够了,直接给不废话。

      如果内存是一点都没了,只能重新去heap中malloc。

  5.山穷水尽——如果真的二级空间配置器一点内存都分配不出来了,那么只能从一级空间配置器中来寻找。

  为什么二级都没有而一级会有呢?

  因为一级中有空间不足时的应对措施,所以就算是失败,也是一级空间配置器来报的错。

  解惑:

  为什么向上对齐ROUND_UP是八个字节而不是四个字节?

  因为我们知道里面的内容是一块单链表,那么肯定有一个指针,那么为了符合64位系统,肯定是8个字节。

  默认情况下用一级空间配置器还是二级空间配置器?

  二级空间配置器。源码中有一个模板类——simple_alloc。

  其中有一个宏——__USE_MALLOC ,如果这个宏被定义了,那么就是用一级空间适配器。

  如果没被定义,那么就是用二级空间适配器。

  这个宏就是决定,谁的别名时alloc。

  而alloc就是STL标准库中默认类参数的成员——

  template <class T,class Alloc = alloc>

  class list{

    ...

  };

  

   

  空间配置器底层使用malloc实现的,所以他定义出来的东西并不是一个对象(malloc不调用构造函数)。

  那么STL标准库开辟空间时是如何才能构建出对象?

  利用定位new表达式,既然开辟了一个空间p,直接new(p) T1(value) 即可。

  所以如果我们要构造STL对象和销毁STL对象分下列部分:

  1.get_node 获取空间——construct 构造对象(定位new)

  2.destroy 销毁对象——put_node 归还空间,如何归还看下一问。

  二级空间配置器的释放?

  首先先判断是否大于128,如果大于则用一级空间配置器的释放,如果小于则挂回free list。

  

  我们了解了construct和destroy是构造和销毁,那么拷贝构造,整体复制,按指定个数复制,都会有定义——

  即uninitialized_copy(),uninitialized_fill(),uninitialized_fill_n()。

  详见《STL源码剖析》,这里不细说,其底层也是运动迭代器在[first,last)上遍历。

原文地址:https://www.cnblogs.com/shy0322/p/9195469.html

时间: 2024-10-08 07:02:37

C++标准库——STL之空间配置器的相关文章

STL 之 空间配置器(allocator)

一.SGI 标准的空间配置器,std::allocator SGI也定义了一个符合部分标准,名为allocator的配置器,但是它自己不使用,也不建议我们使用,主要原因是效率不佳. 它只是把C++的操作符::operator new和::operator delete做了一层简单的封装而已. 二.SGI 特殊的空间配置器,std::alloc 由于SGI 标准的空间配置器只是把C++的操作符::operator new和::operator delete做了一层简单的封装,没有考虑到任何效率上的

【STL】空间配置器剖析(二)

上篇文章点击打开链接主要对于对象的构造含和析构进行了主要说明,这篇文章将对对象构造前的内存配置和对象析构后的空间释放进行深入探索. 好的,话不多说马上进入是正文: 对对象构造前的内存配置和对象析构后的空间释放,由<stl_alloc.h>负责,SGI对此的设计哲学如下: 向system heap要求空间. 考虑多线程的状态 考虑内存不足的应变措施 考虑过多的"小型区块"可能造成的内存碎片问题 C++的内存配置的基本操作是:operator new(),内存释放的基本操作是o

(一)STL剖析——空间配置器

Alloc.h //Alloc.h负责内存空间的配置与释放 //Construct.h负责对象内容的构造与析构 //这两个头文件在memory文件中包含 #pragma once typedef void(*HANDLER_FUNC)(); //一级空间配置器 template <int inst> class __MallocAllocTemplate  { public: static void* Allocate(size_t size)//静态成员函数 { void* result =

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

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

stl 空间配置器理解

理解了一下stl的空间配置器,发现一个比较好的学习方法,跟着代码自己也跟着写一遍,顺便加些注释,可以更加帮助自己理解. 如new,delete一般,分为两个步骤,1,配置空间,2,构造对象(1,析构对象,2,释放空间) 一.构造和析构的基本工具(construct,destroy) 1,construct(构造) template<class T1,class T2> inline void construct(T1 * p,const T2 & value){ new (p) T1(

STL源码分析--空间配置器的底层实现 (二)

STL源码分析-空间配置器 空间配置器中门道 在STL中的容器里都是使用统一的空间配置器,空间配置器就是管理分配内存和销毁内存的.在STL将在heap空间创建一个对象分为两个步骤,第一是申请一块内存,第二是在这块内存中初始化一个对象.首先申请空间是由malloc提供,初始化一个对象时由constructor管理.销毁一个对象也是由两步骤完成,第一是销毁空间上的对象,第二是释放这块内存. 同时,STL的空间配置器分为两级内存,如果申请的内存空间大于128KB,那么就使用第一级空间配置,如果小于,那

C++ STL学习之 空间配置器(allocator)

标签(空格分隔): C++ STL 众所周知,一般情况下,一个程序包括数据结构和相应的算法,而数据结构作为存储数据的组织形式,与内存空间有着密切的联系. 在C++ STL中,空间配置器便是用来实现内存空间(一般是内存,也可以是硬盘等空间)分配的工具,他与容器联系紧密,每一种容器的空间分配都是通过空间分配器alloctor实现的.理解alloctor的实现原理,对内存结构以及数据存储形式会有更清晰直观的认识. 1.两种C++类对象实例化方式的异同 在c++中,创建类对象一般分为两种方式:一种是直接

简单的空间配置器实现

这一节用到的小知识: 1.ptrdirr_t: ptrdiff_t是C/C++标准库中定义的一个与机器相关的数据类型.ptrdiff_t类型变量通常用来保存两个指针减法操作的结果.ptrdiff_t定义在stddef.h(cstddef)这个文件内.ptrdiff_t通常被定义为long int类型. 2.non-trivial constructor/destructor: 意思是"非默认构造函数/析构函数",这里的non-trivial指不是编译器自动生成的(函数)维基百科 我认为

SGI版本空间配置器

1.STL中的空间配置器 在STL中,空间配置器分了2组,分别为一级空间配置器和二级空间配置器,但是它们都有自己各自运用的场合:一般说来,一级空间配置器一般分配的空间大于128B,二级空间配置器的分配空间为小于128B. 其中SGI 中的STL的空间配置器设计哲学如下: (1).向system heap要求申请空间 (2).考虑多线程的状态 (3).考虑内存不足时的应变措施 (4).考虑过多"小型区块"可能造成的内存碎片问题 在剖析源码时,为了将问题控制在一定的复杂度内,以下源码皆排除