最近看了《STL源码剖析》和侯捷老师的STL课程,打算做一个小型的STL,在增加项目经验的同时也顺带复习STL和数据结构相关的知识。整个系列完全参考岚岚路的博客和github上的一个STL项目项目地址
任务
alloc.h作为STL六大部件之一的分配器有着举足轻重的作用,STL的思想将内存的分配释放与对象的构造和析构分离开来,分别在alloc.h和construct.h中实现。
alloc.h的主要思想:考虑到小型区块造成的内存碎片问题,STL设计了二级配置器,第一级直接使用malloc和free,第二级使用较为复杂的内存池。
内存池的示例如下:
alloc.h代码如下:
#ifndef _ALLOC_H_
#define _ALLOC_H_
#include<cstdlib>
namespace mySTL {
class alloc {
private:
enum EAlign{
ALIGN = 8};//小型区块的边界
enum EMaxBytes{
MAXBYTES=128};//上限,超过此大小直接使用malloc第一级分配器
enum ENFreeLists{
NFREELISTS=(EMaxBytes::MAXBYTES/EAlign::ALIGN) };//freelist个数,16
enum ENObjs{
NOBJS=20};//每次增添的节点数
private:
//freelists节点
union obj {
union obj *next; //指向下一块obj的指针
char client[1];
};
static obj *free_list[ENFreeLists::NFREELISTS];//此处调用了上方的宏,只所以使用静态是为了让这部分唯一(不唯一则不安全)
private:
static char *start_free;//内存池的起始位置
static char *end_free;//内存池的结束位置
static size_t heap_size;//堆的大小
//之所以在这里使用静态内存的原因也很清楚,这些数据都是唯一的,不可能同时存在两个,一旦改变(一般也不改变)就是全局一起改变
private:
//将byte上调至8的倍数
static size_t ROUND_UP(size_t bytes) {
return ((bytes + EAlign::ALIGN - 1) / EAlign::ALIGN);
}
//根据区块大小,决定使用第n号free-list,n从0开始计算
static size_t FREELIST_INDEX(size_t bytes) {
return (((bytes)+EAlign::ALIGN - 1) / EAlign::ALIGN - 1);
}
static void *refill(size_t n);
//配置一大块空间,可容纳nobjs个大小为size的区块
static char *chunk_alloc(size_t size, size_t& nojbs);
public:
//外部可以调用的部分
static void *allocate(size_t bytes);
static void deallocate(void *ptr, size_t bytes);
static void *reallacate(void *ptr, size_t old_sz, size_t new_sz);
};//静态方法效率上比实例化要高,这种经常要用的函数静态是最好了,每次实例化都要成本。
}
#endif