STL——空间配置器

STL有6大组件:容器、算法、迭代器、仿函数、配接器、分配器。它们之间的密切关系是STL的精髓所在,容器用来存放数据,而容器存在的前提是要有分配器给它分配内存,接下来需要实现算法,迭代器便作为算法来对容器数据操作的桥梁,算法可以使用仿函数完成不同的策略变化,配接器可修饰或套接仿函数。

说了么辣么多,所有种种始于存在的内存,说清分配器的来龙去脉看来是必不可少喽。本文仅讨论SGI STL的空间配置器。

1. 两级配置器

要说的明白就不能啰嗦,术语定义也不需要,用到了再说。

只需要知道,new一般做了两件事:分配内存与构造对象(delete反之),STL中将这两个阶段分开了!是的,它不再调用new来分配内存,二是调用c式的malloc干活,这样使得:内存的配置由alloc::allocator()负责(alloc是SGI STL的配置器,其它版本STL采用的配置器是allocator),内存释放由alloc::deallocator()负责,对象的构造和析构由全局函数::constructor和::destroy负责。两个分开了!

先看看构造与析构

构造::constuctor接受一个指针p和一个初值value,将初值设定到指针所指的空间上,定义如下:

    //这里使用的是placement new,需要包含头文件<new.h>
    //为什么是这样的写法,new会开辟新空间,所以不会在想要的地方初始化数据,而这里的new是placement new,在p所指地址初始化值即可
    template <class T1, class T2>
    inline void constructor(T1 *p, const T2 & value) {
        new (p) T1(value);          
    }

析构::destroy有两个版本,一个接受指针,可直接析构之;另一个接受first和last迭代器的版本,这时要分两种情形:判断元素的数值型别(value type)是否有trival destructor,如果是则什么都不做,否则就逐个析构,这样可以提高效率。

问题来了,什么是value type?什么又是trival destructor?
暂且这么来理解,如果元素是int型,根本就不需要调用析构函数,所以value type判断该元素型别是int,其具有trival destructor(没什么卵用的析构),那么不需要逐个调用析构函数了,岂不是很清爽!对于复杂对象(要分配空间)的型别,其destructor当然是non_trival。

空间配置和释放

重要的事情再说一遍:SGI以malloc()和free()完成内存配置与释放。为了简洁,只说配置,不说释放。

为了尽量减少小型区块造成内存碎片的问题,STI设计了双层配置器,这两级的处理关系如下:
如果定义了__USE_MALLOC则alloc为第一级配置器,否则为第二级。

  1. 第一级配置器会根据需求分配内存(malloc()),不够用时调用oom_malloc()(这个会一直尝试从堆中获取区块for(;;))。
  2. 第二级配置器首先判断所需区块大小是否大于128bytes,是则调用第一级配置器,否转3。
  3. 从freelist中找(8字节对齐)对应区块,有则返回之,并调整freelist,否转4。
  4. 现在freelist中对应区块不够用,那么调用refill函数,默认从memory pool(内存池)中chunk_alloc()20个同等大小的新区块挂到freelist上,不过不够20个,但够1个,就拔出这不足20个的区块给freelist,如果1个都不够啦,就需要调用malloc从heap中配置内存,为内存池注入活水。

问题又来了:什么是freelist?
自由链表,SGI中定义的是freelist[16],分别指向块大小为(i+1)*8bytes 的内存区,然后相同大小的区块会形成一个链表,有点类似与邻接表这种数据结构。

2. 内存的基本处理工具

STL定义的5个全局函数:constructor()、destroy()、uninitialized_copy()、uninitialized_fill()、uninitialized_fill_n()。

后三个函数是的内存配置与对象构造行为分离开来,copy是将未初始化的输出去初始化为对应的输入去数据;fill是对区间内每个迭代器都初始化为给定值x,fill_n将区间起始处后n个迭代器初始化为x。

三者具体实现步骤: 判断value_type是否为POD, 是则调用fill_n(直接赋值),否则调用构造函数。

问题来了,什么是POD?
POD指Plain Old Data,该型别数据拥有trival ctor/dtor/copy/assignment函数,简单的也可以理解为int。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章