C++空间分配器简述学习笔记
- 空间分配器 std:: allocator
std::allocator提供的接口 ---> 位于头文件<stl_alloc.h>
对象的定义和空间的分配是分开的。
template<typename T>
class allocator
{
typedef Alloc _alloc 实现层
public:
//用来申请空间,分配新的空间
T * allocate(size_type n);
//用来彻底回收空间
void deallocate(T *,size_type n);
//在制定位置内存中,通过复制构造放入一个新元素
void construct(T * ,const T &_value);
//只是销毁对象,并不回收空间
void destroy(T * )
}
- 内存碎片: 内部碎片 和 外部碎片
STL采用了两级空间配置器
- 当 < = 128字节的,采用内存池分配。
- > 128字节,直接malloc --->一级配置器
- 一级配置器就是malloc 和free 的封装 __malloc_alloc_template
- 二级配置器,__defaule_alloc_template
-
- 内存池(堆空间),16个自由空闲链表存储区,每一个都存储着一个单链表的首地址(其中链表的每个节点都是8的倍数),从第一个开始一次是8的倍数,第一个就是8个字节,第二个是16字节,24,32,40,48,56,64,72,80,88,96,104,112,120,128、、最后一个是128字节,如果要获取空间时,直接以O(1)的时间分配空间。
- 16个自由空闲链表 ---->数组,初始值时,都是空的
-
- static Obj* _S_free_list[16]
union Obj
{
union Obj * _M_free_list_link;
char _M_CLIENT_DATA[1];
};
- 内存池
-
- static char * _S_start_free;
- static char * _S_end_free;
- 从堆中获取的最大空间
-
- static char * _S_heap_size
函数:
- _S_free_list_index(size_t bytes); //找到相应字节大小的下标值
- _S_round_up(size_t bytes); //向上返回一个8的倍数
- _S_refill (size_t n);
- int nobjs=20; //一次性开辟20个相同n字节空间的块。原理:以空间换时间。(因为alloc一般用于容器,避免了频繁开空间)
- _S_chunk_alloc( n ,nobjs) ; //开辟空间的函数
第一次调用:
-
- _total_byttes= n*nobjs=32*20=640;
- _bytes_left =_S_end_free - _S_start_free
- 初始时,没有空间 , bytes_to_get= 2*_totle_bytes=1280;
- _S_start_free=malloc(1280);
- _S_heap_size +=bytes_to_get;
-
- _total_byttes= n*nobjs=32*20=640;
- _bytes_left =_S_end_free - _S_start_free=1280
- _total_byttes= n*nobjs=32*20=640;
- _bytes_left =_S_end_free - _S_start_free=1280
- _S_refill( ); //划分细化