第2章 空间配接器(allocator)

来源:互联网 发布:云游seo 编辑:程序博客网 时间:2024/06/07 19:32

第2章 空间配接器(allocator)

SGI STL的配置器与标准规范不同,其名称是alloc而非allocator,而且不接受任何参数。虽然SGI也定义一个符合部分标准、名为allocator的配置器,但SGI自己未使用它,也不建议使用。主要原因是效率不佳,只把C++的::operator new和::operator delete做一层包装。

因此,在程序中:vector<int, std::allocator<int> > iv;   //in VCvector<int, std::alloc> iv;             //in GCC

1 SGI特殊的空间配置器,std::alloc

一般而言,对于C++内存配置操作和释放操作

class Foo {...}Foo *pf = new Foo;delete pf;

这其中的new算式内包含两阶段操作:

(1)调用 ::operator new 配置内存;(2)调用Foo::Foo()构造对象内容。

delate算式也内含两阶段操作:

(1)调用Foo::~Foo()将对象析构;(2)调用 ::operator delete 释放内存。

为了精密分工:STL alloctor决定将两阶段操作区分开来。配置器定义在<memory>之中,包含以下两个头文件:

#include <stl_alloc.h> —内存配置 alloc::allocate() 负责,内存释放 alloc::deallocate() 负责;

#include <stl_construct.h> —对象构造 ::construct() 负责,对象析构 ::destroy() 负责。

该头文件中定义了全局函数construct()和destroy(),负责对象的构造和析构。

T1 *pT1 = new(p) T1(value);  //在p所指的内存空间中 构造一个新T1类的实例。即placement new.注:如果你想在预分配的内存上创建对象,用缺省的new操作符是行不通的。要解决这个问题,你可以用placement   new构造。它允许你构造一个新对象到预分配的内存上。

2 对象的构造与析构

construct()和destroy()这两个作为构造和析构只用的函数被设计为全局函数,,符合STL规范。此外,STL还规定配置器必须拥有名为construct()和destroy()的两个成员函数,然而真正在SGI STL中的名为std::alloc的配置器并未遵守这一规则。

3 空间的配置与释放(内存的配置与释放),std::alloc

对象构造前的空间配置和对象析构后的空间释放,由<stl_alloc.h>负责。

C++内存配置基本操作是::operator new(),内存释放的基本操作是::operator delete()。这两个全局函数相当于C的malloc()和free()函数。SGI正是以malloc()和free()完成内存的配置与释放。

考虑小型区块可能造成的内存破碎问题,SGI设计了双层级配置器:

第一级配置器__malloc_alloc_template,直接使用malloc()和free();

第二级配置器__default_alloc_template,SGI第二级配置器的做法是,如果区块够大,超过128bytes时,就移交第一级配置器处理。当区块小于128bytes时,则以内存池(memory pool)管理。内存池以malloc()配置而得。如果内存不足,转调用第一级配置器。

此法又称之为次层配置(sub-allocation):每次配置一大块内存,并维护对应之自由链表(free-list)。为了方便管理,SGI第二级配置器会主动将任何小额区块的内存需求量上调至8的倍数,并维护16个free-lists,各自管理大小分别为8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128 bytes的小额区块。

注:配置器本质是一个模板类,而且:

typedef __malloc_alloc_template alloctypedef __default_alloc_template alloc

4 空间配置函数allocate()、空间释放函数deallocate()

①配置器_default_alloc_template拥有配置器的标准接口函数allocate()。此函数首先判断区块的大小,大于128bytes就调用第一级配置器,小于128bytes就检查对应的free list。如果free list之内有可用的区块,就直接拿来用,如果没有可用区块,就将区块大小上调至8倍数边界,然后调用refill(),准备为free list重新填充空间。新的空间将取自内存池(经由chunk_alloc()完成)。缺省取得20个新节点(新区块),万一内存池空间不够,获得的节点数可能小于20。

②配置器__default_alloc_template拥有配置器标准接口函数deallocate()。该函数首先判断区块大小,大于128bytes就调用第一级配置器,小于128bytes就找对应的free list,将区块回收。

5 内存基本处理工具

STL定义有五个全局函数,作用于未初始化空间上。

1. construct()2. destroy()3. uninitialized_copy()4. uninitialized_fill()5. uninitialized_fill_n()

其中,使用下面三个低层次函数,应该包含<memory>,不过SGI把他们实际定义在<stl_uninitialized>

原创粉丝点击