作用:帮助容器配置空间存放信息
SGI空间配置器
标准空间配置器allocator:效率不好,只对::operator new和::operator delete做一层封装
特殊空间配置器alloc :将new算式分为两阶段:用::operator配置内存,构造对象;
将delet算式分为两阶段:析构对象,用::operator delete释放内存
特殊空间配置器
内存配置:allocate(),判断区块大小,大于128字节调用一级配置器,小于检查自由链表中若有可用区块直接使用,否则为自由链表重新填充空间
内存释放:deallocate(),判断区块大小,大于128字节调用一级配置器,小于则找到对应自由链表,进行区块回收。
对象构造:construct()
对象析构:destroy()
双层配置器
一级配置器:使用malloc(),free()进行内存的分配与释放。类名:__malloc_alloc_template。
二级配置器:小于128字节时,采用内存池,维护自由链表,可从自由链表进行内存的分配与释放。内存需求量需上调为8的倍数。类名:__default_alloc_template。
下面的程序是关于第一级和第二级配置器
#include<iostream>
#include<string>
#include<vector>
#include<iterator>
#include <new.h> //使用placement new
#include <stddef.h> //常用常量
#include <limits.h> //类型最值的常量
//#include <algobase.h>
#include <memory> //STL配置器定义于此
//以下是SGI_STL_空间配置器的头文件
//#include <stl_construct.h> //定义有全域函式
#include <stl_uninitialized.h> //定义了全局函数,赋值大内存数据
using namespace std;
template<class T>
inline T* allocate(ptrdiff_t size,T* )
{
set_new_handler(0);
T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
if(tmp==0)
{
cerr<<"内存分配失败"<<endl;
exit(1);
}
return tmp;
}
template<class T>
inline void deallocate(T* maBlock)
{
::operator delete(maBlock);
}
template<typename T>
class MaAllocator
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
public:
pointer allocate(size_type n)
{
return ::allocate((differenc_type)n,(pointer)0);//::表示在全局域
}
void deallocate(pointer p)
{
::deallocate(p);
}
pointer address(reference x){return (pointer)&x;}
const_pointer address(const_reference x){return (const_pointer)&x;}
size_type init_page_size()
{
return max(size_type(1),size_type(4096/sizeof(T)));
}
size_type max_size() const
{
return max(size_type(1),size_type(UINT_MAX/sizeof(T)));
}
};
//特化版本:
template<>
class MaAllocator<void>
{
public:
typedef void* pointer;
};
template<class T1,class T2>
inline void construct(T1* p,const T2& value)//作用:将初值设定到指针所指的空间上
{
new(p) T(value);//调用T1::T1(value)
}
//销毁函数不返回任何类型
template<typename T>
inline void destroy(T* pointer)//将指针所指之物析构掉
{
pointer->~T();//调用~T()
}
/*接受两个迭代器,找出元素的数值型别,用_type_traits<>求最适当措施
对迭代器进行析构,由于析构的东西多,必须判定析构函数是否真正有用,用value_type判定
若为true_type,表明T为简单类型,是无用析构函数,则什么都不做*/
template<typename ForwardIter>
inline void destroy(ForwardIter first,ForwardIter last)
{
_destroy(first,last,value_type(first));//用value_type获取型别
}
//判断元素的数值型别(value_type)是否有trivial destructor(无用的析构函数,即系统自带的)
template<class ForwardIterator,class T>
inline void _destroy(ForwardIterator first,ForwardIterator last,T*)
{
/*_type_traits<T>这个模板类根据不同的T类型定义不同的has_trivial_destructor,如果T是简单类型
就定义为_true_type类型,否则定义为_false_type类型。这两个类。*/
typedef typename _type_traits<T>::has_trivial_destructor trivial_destructor;//?
destroy_aux(first,last,trivial_destructor());//?
}
//如果元素的数值型别为non-trivial destructor,T不是简单类型为_false_type,为有效析构函数
template<class ForwardIterator,class _false_type>
inline void _destroy_aux(ForwardIterator first,ForwardIterator last,_false_type)
{
for(;first!=last;first++)
{
destroy(&*first);
}
}
//如果元素的数值型别为trivial destructor,T为简单类型
//template<class ForwardIterator,class _true_type>
//inline void _destroy_aux(ForwardIterator first,ForwardIterator,_true_type)
//{
//}
//是对迭代器为char* ,wchar_t*
inline void destroy(char* ,char* ){}
//inline void destroy(wchar* ,wchar* ){}
inline void destroy(wchar_t*,wchar_t*){}
template<class T,class Alloc>
class simple_alloc
{
public:
//static T* allocate(size_t n)
static T* allocate(size_t n)
{
return 0==n?0:(T*)Alloc::allocate(n*sizeof(T));
}
static T* allocate()
{
return (T*)Alloc::allocate(n*sizeof(T));
}
static void deallocate(T* p,size_t n)
{
if(0!=n)
{
Alloc::deallocate(p,n*sizeof(T));
}
}
static void deallocate(T* p)
{
Alloc::deallocate(p,sizeof(T));
}
};
template<typename T,typename Alloc = alloc>
class MaVector
{
public:
typedef T value_type;
protected:
//专属空间配置器,每次配置一个元素
typedef simple_alloc<value_type,Alloc> data_allocator;
void deallocate()
{
if(1)//?
{
data_allocator::deallocate(start,end_of_storage-start);
}
}
};
template<int inst>
class _malloc_alloc_template
{
private:
//一下都是函数指针,代表的函数处理内存不足情况,oom=out of memory
//static void* oom(size_t n)//内存分配溢出时的分配
//static void* oom_malloc(size_t )
//{
//}
static void* oom_realloc(void* ,size_t)
//static void* oom_realloc(void* ,size_t )
//{
//}
static void(*__malloc_alloc_oom_handler)//不能有2个下划线
//static void(*_malloc_alloc_oom_handler())
//{
//}
public:
static void* allocate(size_t n)
{
//第一级配置器用malloc分配
//void* result = oom_malloc(n);
void* resule = malloc(n);
if(0==result)//分配溢出时,改用oom_malloc分配
{
result = oom_malloc(n);
}
return result;
}
//static void deallocate()//必须释放指针的内存
static void deallocate(void* p)
{
free(p);//第一级配置器使用free
}
static void* reallocate(void* p,size_t old_sz,size_t new_sz)
{
//第一级配置器直接使用realloc
void* result = realloc(p,new_sz);
if(0==result)
{
result = oom_realloc(p,new_sz);
}
return result;
}
//下面是自定义的内存溢出处理方法
static void(*set_malloc_alloc_oom_handler(void (*f)()))()//为什么最后还多一个()
{
void(*old)() = _malloc_alloc_oom_handler;
_malloc_alloc_oom_handler = f;
return(old);
}
void* oom_malloc(size_t n)
{
void* result;
void(*my_malloc_handler());//?
for(;;)//不断释放,配置,在释放,再配置
{
my_malloc_hander = _malloc_alloc_oom_handler;
if(0==my_malloc_handler)
{
throw std::bad_alloc;
}
(*my_alloc_handler());
//result = my_alloc_handler;//分配多个字节
result = malloc(n);
if(result)
{
return result;
}
}
}
//void* _malloc_alloc_template<inst>::oom_malloc(size_t n)
//template<int inst>
//void(*_malloc_alloc_template<inst>::_malloc_alloc_oom_handler)()=0;
void* oom_realloc(void* p,size_t n)
{
void* result;
void(*_my_malloc_handler());
for(;;)
{
my_malloc_handler = _malloc_alloc_oom_handler;
if(0==my_malloc_handler)
{
throw std::bad_alloc;
}
(*my_malloc_handler());//执行处理函数
result = realloc(p,n);
if(result)
{
return result;
}
}
}
};
typedef _malloc_alloc_template<0> malloc_alloc;
//第二级配置器
union obj//obj可视为指另一个针指向相同形式的obj
{
union obj* free_list_link;
char client_data[1];
};
template<bool threads,int inst>
class _default_alloc_template
{
private:
//ROUND_UP()将比特上调为8的倍数
static size_t ROUND_UP(
)
}
enum {_ALIGN = 8};//小数据块的上调边界
enum {_MAX_BYTES = 128}; //小型区块的上限
enum {_NFREELISTS = _MAX_BYTES/_ALIGN};//自由链数目
int main(int argc,char *argv[])
{
cout<<"2.2:具备次配置力的SGL空间配置器"<<endl;
cout<<"STL Allocator的函数:"<<endl;
cout<<"内存申请:alloc::allocate()负责"<<endl;
cout<<"内存释放: alloc::deallocate()负责"<<endl;
cout<<"对象构造: 全局 ::construct()负责"<<endl;
cout<<"对象析构:全局 ::destroy()负责"<<endl;
cout<<"第一回合:SGI特殊的空间配置器"<<endl;
cout<<"new 运算式含量阶段操作:1调用::operator new 配置内存,2调用构造函数构造对象内容"<<endl;
cout<<"delete阶段操作: 调用析构函数将对象析构,2调用::operator delete释放内存"<<endl;
cout<<"placement new 定义:是重载operator new的全局版本,不能够被自定义版本代替,忽略size_t参数,只返还第二个参数"<<endl;
cout<<" 用法:pi = new(ptr) int;ptr指向内存缓冲器,比new多了一个“(内存地址)”参数placement new(替换符new)返回值是这个被构造对象的地址"<<endl;
cout<<" 适用:时间要求高;长时间运行;执行垃圾收集器"<<endl;
cout<<"new:不能被重载。先调用operator new分内存,调用构造函数初始化内存"<<endl;
cout<<"operator new:实现不同内存分配应重载operator new"<<endl;
cout<<"placement new:是operator new的一个重载版本。不分配内存,只返回已分配内存指针。不能删除,但需调用析构函数"<<endl;
cout<<"第二回合:构造和析构基本工具construct与destroy"<<endl;
cout<<"第四回合:空间的配置与释放: std::alloc"<<endl;
cout<<"::operator new()内存配置的基本操作是全局函数=malloc"<<endl;
cout<<"小型区块内存破碎解决方案:设计双层级配置器。第1层用:malloc,free;第二层视情况而定"<<endl;
cout<<"配置区<128B时,采用内存池。"<<endl;
//测试配置器是用1级,还是1,2级同时开启
//#ifdef _USE_MALLOC
// typedef _malloc_alloc_template<0> malloc_alloc;
// typedef malloc_alloc alloc;//令alloc为第一级配置器
//#else
// //另alloc为第二级配置器
// typedef _default_alloc_template<_NODE_ALLOCATOR_THREADS,0> alloc;
//#endif
cout<<"第5回合:第一级配置器__malloc_alloc_template"<<endl;
cout<<"new-handler机制:系统内存配置无法满足时,调用你指定的函数,然后抛bad_alloc异常"<<endl;
cout<<"SGI以malloc而非::operator new 来配置内存"<<endl;
cout<<"第二级配置器:__default_alloc_template"<<endl;
cout<<"次层配置:区块小于128bytes,以内存池管理。"<<endl;
getchar();
return 0;
}