2.空间配置器

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

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

    class Foo{…..}

    Foo* pf = new Foo;

    delete pf;

       

    new包含两阶段操作 (1)调用 ::operator new 配置内存 (2)调用 Foo::Foo() 构造对象内容。

    delete也包含两阶段操作 (1)调用 Foo::~Foo() 将对象析构 (2)调用::operator delete 释放内存。

       

    SGI<memory> 内含以下两个文件

    #include<stl_alloc.h> //负责内存空间的配置与释放

    #include<stl_construct.h> //负责对象内容的构造与析构

       

  • 构造和析构基本工具: construct() 和 destroy()

    destroy有两个版本,第一版本接受一个指针,直接调用该对象的析构函数。

    第二版本接收 frist 和 last 两个迭代器, 将 [frist, last)范围内的所有对象析构掉。

    首先利用 value_type () 获得迭代器所指对象的型别, 再利用 _type_traits<T> 判断该型别支持的析构函数是否是无关痛痒(trivial destructor ),若是,则什么也不做就结束,若不是,以循环寻访整个范围,并在循环中每经历一个对象就调用第一个版本的destroy()。

       

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

       

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

    (1)向system heap 要求空间

    (2)考虑多线程状态

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

    (4)考虑过多"小型区块"可能造成的内存碎片问题。

       

    考虑到小型区块所可能造成的内存破碎问题,SGI设计了双层级配置器。第一级配置器直接使用malloc() 和free(), 第二级配置器则视情况采用不同的策略:当配置区块超过 128bytes 时,视之为"足够大",便调用第一级配置器;当小于128bytes时,视之为"过小",为了降低额外的负担,采用复杂的 memory pool整理方式。

       

       

       

  • 第一级配置器 __malloc_alloc_template

    SGI 第一级配置器的 allocate() 和 realloc()都是在调用 malloc() 和 realloc() 不成功之后,改调用 oom_malloc() 和 oom_realloc() 两者都有内循环,不断调用"内存不足处理例程",期望在某次调用后获得足够的内存而圆满完成任务,但如果"内存不足处理例程"未被客户端设定,便会抛出异常。

       

  • 第二级配置器 __default_alloc_template

    第二级配置器多了一些机制,避免太多小额区块造成内存的碎片。小额区块带来的不仅仅是内存碎片的问题,配置时的额外负担也是很大的问题。系统要靠这多出来的空间来管理内存。区块愈小,额外负担所占比例就越大,就越浪费。

       

    SGI第二级配置器的做法是,如果区块够大,超过128bytes时,就移交第一级配置器,当小于128bytes时,则以内存池(memory pool)管理,此法又称次层配置:

    每次配置一大块内存,并维护之自由链表,下次若再有相同大小的内存需求,就直接从free-lists中拔出,如果客户端释还小额区块,就由配置器回收到free-lists中。 为了方便管理,SGI第二级配置器会主动将任何小额区块的内存需求量上调至8的倍数,并维护16个 free-lists,各自管理大小为8,16,24,32,40,56,64,72,80,88,96,104,112,120,128bytes

       

  • 空间配置函数allocate()

  • 空间释放函数deallocate()

  • 重新填充 free lists

    当它发现free lists中没有可用的区块时,就调用refill(),准备为free list 重新填充空间。新的空间将取自内存池。

       

  1. 内存基本处理工具

       

  • uninitialized_copy()

    uninitialized_copy()使我们能够将内存的配置与对象的构造行为分离开来。

    如果作为输出目的地[result, result + (last - frist)) 范围内每一个迭代器都指向未初始化区域, 则 uninitiated_copy() 会使用 copy consturctor, 给身为输入来源之[frist, last] 范围内的每一对象产生一份复制品,放进输出范围中。

       

       

       

  • Uninitialized_fill()

       

       

  • Uninitialized_fill_n()

   

Uninitialized_fill_n()能够使我们将内存配置与对象构造行为分离开来,它会为指定范围内的所有元素设定相同初值

   

   

接受三个参数

(1)迭代器指向与初始化空间的起始处

(2)n 表示欲初始化空间的大小

(3)x 表示初值

   

首先萃取出迭代器Frist 的型别再判断是否是POD型别

POD指plain old data, 标量型别

   

   

转载于:https://www.cnblogs.com/h3mmm/p/9821093.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值