STL从零开始-002 空间配置器概述
一、什么是空间配置器
STL空间配置器主要负责“内存管理”、“对象构造析构”。对象的创建和销毁过程细分可以由以下构成:申请内存、调用构造函数;调用析构函数、释放内存。为了提高效率,stl将两个阶段的操作分开实现。
- 内存管理:alloc.h 主要负责内存的申请(alloc::allocate)和释放(alloc::deallocate)
- 对象管理:construct.h 主要负责对象构造(::construct)和析构(::destory)
这两部分内容被封装在allocator.h中,该头文件被具体的容器调用。
二、内存管理
alloc提供的接口有3个,如下所示:
- static void* allocate(size_t n); 申请大小为n的内存
- static void* deallocate(void *p,size_t n); 删除p所指向的大小为n的内存
- static void* reallocate(void *p, size_t old_size, size_t new_size); 调整p所指向内存的大小为new_size
C++内存配置基本操作是::operator new() 和operator delete()。这两个全局函数相当于C语言中的malloc和free,所以SGI版本的stl以malloc和free完成内存的配置和释放。malloc这一函数涉及到系统调用brk、nmap,所以开销很大,如果你申请内存非常小而去调用malloc性价比不高。通常情况下,都可以通过引入一个中间件来解决,像是内存和cup之间引入缓存一般。内存管理引入内存池、空闲内存链表等措施来处理小型内存的申请。
这一策略的具体实现是:设计一二级配置器,以128bytes为界限。
- 一级内存分配:当申请的内存超过128bytes时,直接调用malloc申请
- 二级内存分配:当申请的内存小于128bytes时,将通过维护的内存池memory_pool、空闲内存链表free_list,进行内存划分。
二级内存配置具体涉及到如下一些函数,大概有个印象,无需记住,具体实现过以后记忆会很深刻。
M_round_up(size_t n) |
功能:内存上调 返回类型和值:size_t、(8\16\24..等值,如传入6,则上调至8)
|
M_freelist_index(size_t n) |
功能:计算出n所对应的free_list空闲链表的下标 返回类型和值:size_t、(0~15) |
M_refill(size_t size) |
被调用情况:free_list[xxx]下没有可用的内存块 功能: ①返回可用内存块给调用者 ②向内存池请求内存,并对返回的内存按大小划分成块。 返回类型和值:void*、分配成功返回地址 |
M_chunk_alloc(size_t size, size_t& nobj) |
被调用情况:当内存池中内存不足够供给m_refill调用分配时,调用 功能: ①向堆区申请内存 ②堆区内存不足时,将free_list中内存回收到内存池中,供重新分配 返回类型和值:void*、申请成功返回内存地址 |
三、对象管理
对象构造主要了解placement new,也就是new() T()这句话的意思,相关讲解链接:
- https://www.cnblogs.com/slgkaifa/p/6887887.html
- https://blog.****.net/zhangxinrun/article/details/5940019
四、整体框架设计
allocator.h对外提供接口,主要是对alloc.h和construct.h进行封装。一二级配置器都在一个头文件alloc.h中实现,一级配置器在__alloc类中实现,__alloc的函数被二级配置器alloc所调用。通过下面这个图基本就可以把整个内存管理的框架了。