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

空间的配置与释放std::alloc

1、对象构造前的空间配置与对象析构后的空间释放,由<stl_alloc.h>负责。SGI对此设计哲学如下:

a)向system heap要求空间

b)考虑多线程状态

c)考虑内存不足时的应变措施

d)考虑过多“小型区块”可能造成的内存碎片(fragment)问题

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

2、SGI双层级别的配置器

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

第一级配置器:直接使用malloc()和free(),使用malloc()、free()、realloc()等C函数执行实                           际的内存配置、释放、重配置操作。它不是直接使用C++ new-handler机制。因此并不是使用::operator new来配置内存的。

第二级配置器:视情况采用不同的策略:

1)当配置的区块超过128bytes时,视之为足够大,此时便调用一级配置器。

2)当配置区块小于128bytes时,视之为“过小”,为了降低额外负担(overhead),便采用复杂的memory pool(内存池)管理方式,而不再求助于第一级配置器。

            a)维护16个自由链表(free lists)负责16种小型区块的配置能力。

            b)内存池(memory pool)以malloc()配置而得。

            c)如果内存不足,则转去调用第一级配置器,因为第一级配置器那里有处理程序。-                 --------不断尝试释放、配置、再释放、再配置

3、C++ new-handler机制

所谓C++ handler机制就是你可以要求系统在内存配置需求无法满足时,调用一个你所指定的函数。换句话说,一旦::operator new无法完成任务,在抛出std::bad_alloc异常之前会先调用由用户事先指定的处理例程。该处理例程就被称为new-handler。

4、一般而言,我们所习惯的C++内存配置操作和释放操作是这样的:

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

 这其中的new实际上包含两个阶段操作:

(1)new表达式调用一个,名为::operator new(或者::operator new[])的标准库函数该函数分配一个足够大的、原始的、未命名的内存空间以便存储特定类型的对象(或者数组)。

(2)编译器运行相应的构造函数以便构造这些对象,并为其传入初始值(换句话说就是调用Foo::Foo()构造对象内容)。

这其中delete实际上也是分两个阶段的操作:

(1)对pf所指向的对象或数组执行相应的析构函数。

(2)调用::operator delete(或者::operator delete [])释放内存。

5、为了精密分工,STL allocator决定将这两个阶段分开来,内存配置由alloc::allocate()负责,内存构造由alloc::deallocate()负责;对象构造由::construct()负责,对象析构由::destroy()负责。

STL标准告诉我们,配置器定义于<memory>中,SGI <memory>内含以下两个文件:

#include <stl_alloc.h> //负责内存空间配置与释放
#include <stl_construct.h> //负责对象内容的构造与析构

6、术语----placement new(也叫定位new

如果你想在一个已经分配的内存中创建一个对象,使用new是不行的。placement new允许你在一个已经分配的内存中构造一个新的对象。

7、关于析构函数

如果用户不定义自己的析构函数,而是使用系统默认的析构函数,则说明析构函数基本没有什么作用(但默认会被调用)我们称之为trivial destruvtor.

destroy函数会判断将要释放的迭代器所指向的对象的类型有没有trivial destructor;若有,则什么也不做。若没有,则执行真正的destroy

8、怎样单独分配一个原始的为构造的内存区域?(如何调用原生态的operator new)

//如果需要的是void类型,size_t是具体大小
void *p = operator new(size_t);
//如果需要的是int类型
int *p = static_cast<int *>(operator new(size_of(int)));

因为由原生态operator new分配的内存所返回的指针都是void类型的,所以需要进行强制类型转换

你可能感兴趣的:(数据结构,C++,STL)