前面说到了如果需要的内存空间大于128bytes就是用第一级配置器,那么现在就来看下,如果需要的内存空间小于128bytes的分配方法:
第二级配置器。
在书中侯捷分析了,对于空间小于128bytes的,把空间分成16种类型的小额区间:8bytes,16bytes,24bytes,32bytes,.....128bytes。如果需要10bytes那么就在16bytes这种类型中取,如果需要n bytes那么就在(n+8-1)&(~7) bytes这种类型里面去。
那么这16中类型的小额区间分别是怎么保存地址信息的呢,它是通过一个联合体:
union obj{
union obj* free_list_link;
char client_date[1];
};
通过free_list_link指针指向下一个空余空间,同时因为free_list_link是一个obj指针,所以通过这个指针又可以指向下一个空余空间。
这就相当于一个栈,栈中的每个元素都对应一段空余空间。但是它并没有单独分配空间来保存这些地址,而只是保存了一个头指针,通过这个头指针来访问这些空间。
那么既然我们有16种类型的小区间,那么我们就有16个“栈”。
当我们需要分配一段区间时,首先我们把这段区间分类,看它是哪种类型的,然后在这种类型的“栈”中取出栈头节点,那么这个栈头节点的地址就是我们分配到的空间地址了。
然后问题来了,我们怎么知道这些栈头的地址呢,在STL中,它通过一个数组来保存了这些地址:
static obj* free_list[__NFREELISTS];
下面来看一段代码:
在这段代码中 我们可以看到当需要的空间大于128的时候就直接调用第一级配置器去分配空间,其实就是调用malloc来分配,
然后但空间小于128的时候:
首先是:size_t index=FREE_LIST_INDEX(n);
得到我们需要空间的类型。
然后:result=free_list[index];
这就是“栈头”地址,也就是我们需要返回的地址。
当然 最后要重新把栈头地址 指向下一个空余空间:
free_list[index]=result->free_list_link;
上面的就是基本的思想,但是我们一开始怎么得到空余空间呢,或者说但我们某一类型的空余空间用完了该怎么办呢:
在STL中,它有一个内存池,通过两个指针指向这段内存:
private:
static void *start_free;//内存池的开始位置
static void *end_free;//内存池的结尾位置
这段内存池是通过malloc或得到的,但是这不是重点重点是,如果我们需要 total_bytes大小的空间但是我们剩下的空间bytes_left不足以满足它怎么办:
STL中分了两部:
第一步:
吧剩下的空间bytes_left先配给适当的类型空间:
第二步:
通过malloc来分配空间,如果分配失败,那么就从其它类型空间分区里面调节:
主要的思想就是这上面了。
然后把完整的代码按照书上面的内容自己写了遍: