空间配置器:
作用:帮助容器配置空间存放信息
SGI空间配置器
标准空间配置器allocator:效率不好,只对::operator new和::operator delete做一层封装
特殊空间配置器alloc :将new算式分为两阶段:用::operator配置内存,构造对象;
将delet算式分为两阶段:析构对象,用::operator delete释放内存
特殊空间配置器
内存配置:allocate(),判断区块大小,大于128字节调用一级配置器,小于检查自由链表中若有可用区块直接使用,否则为自由链表重新填充空间
内存释放:deallocate(),判断区块大小,大于128字节调用一级配置器,小于则找到对应自由链表,进行区块回收。
对象构造:construct()
对象析构:destroy()
下面的程序是设计一个简单的空间配置器
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <new> //占位符new的头文件,就是重载的new,不分配内存,在已给的内存运行构造函数
//placement new 实现了在指定内存弟子上用指定类型的构造函数来构造一个对象的功能。例:new(p)A(3) 等同于 p->A::A(3)
#include <cstddef> //常用常量 ptrdiff_t(与机器相关的数据类型,保存两个指针相减的结果,正负皆有可能),size_t
#include <cstdlib> //定义杂项函数和内存分配函数 exit()
#include <climits> //定义数据类型最值的常量 UNIX_MAX
using namespace std;
namespace MaChao
{
template <class T>
inline T* _allocate(ptrdiff_t size,T*)
{
//卸除new-handler,传递空指针给set_new_handler,operator new分配内存不成功时就会抛出一个标准的std::bad_alloc类型的异常
set_new_handler(0);//?
/*operator new默认首先调用分配内存的代码,得堆空间,成功返回;失败,则调用new_handler。::operator new 调用了原有的全局的new,
实现了在分配内存之前就输出一句话/全局的operator new可以重载,但是就不能再递归用new来分配内存,只能使用malloc*/
T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
if(0==tmp)
{
cerr<<"内存不够,分配失败"<<endl;
exit(1);
}
return tmp;
}
template<class T>
inline void _deallocate(T* buffer)
{
::operator delete(buffer);
}
//inline void _construct(T1* p,const T2* value)
template<class T1,class T2>
inline void _construct(T1* p,const T2& value)
{
new(p) T1(value);//placement new的使用
}
template<class T>
inline void _destroy(T* ptr)
{
ptr->~T();
}
template <class 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;//difference_type 是序列容器中两个元素地址之间差异的有符号整数类型
//重新绑定类型U的分配器
template <class U>
struct rebind
{
typedef MaAllocator<U> other;//?
};
//配置存储n个对象的空间,const void* = 0 作用:增进区域性
pointer allocate(size_type n,const void* hint=0)
{
return _allocate((difference_type)n,(pointer)0);//?
}
void deallocate(pointer p,size_type n)
{
_deallocate(p);
}
void construct(pointer p,const T& value)
{
_construct(p,value);
}
void destroy(pointer p)
{
_destroy(p);
}
//Pointer address(Pointer p)//地址用引用
pointer address(reference x)
{
return (pointer)&x;
}
const_pointer const_address(const_reference x)
{
return (const_pointer)&x;
}
//返回可成功配置的最大量
size_type max_size() const
{
return size_type(UINT_MAX/sizeof(T));
}
//public:
MaAllocator(){}
MaAllocator(const MaAllocator& other){*this = other;}
//泛化的拷贝构造函数
template<typename U>
MaAllocator(const MaAllocator<U>& m){*this = m;}
~MaAllocator(){}
template<typename Pointer,typename Reference>
Pointer address(Reference x) const;//返回某个对象的地址 a.address(x)=&x
template<typename Const_Pointer,typename Const_Reference>
Const_Pointer address(Const_Reference& x) const;//返回某个常对象的地址
Pointer allocate(size_type n,const void* = 0);//必须用const void* = 0
template<typename Pointer,typename size_type>
Pointer allocate(size_type n,const void* = 0);//配置存储n个对象的空间,const void* = 0 作用:增进区域性
template<typename Pointer,typename size_type>
void deallocator(Pointer p,size_type n);//归还先前配置的空间
template<typename size_type>
size_type max_size() const;//返回可成功配置的最大量
template<typename Pointer>
void constructor(Pointer p,const T& x);//T必须先构造出来
void construct()
template<typename Pointer,typename T>
void constructor(Pointer p,const T& x);//等价于 new(const void*)p) T{x}
template<typename Pointer>
void destroy(Pointer p);//等同于p->~T{}
};
//new_handler是一个自定义的函数指针,指向没有输入参数也没有返回值的函数
typedef void (*new_handler)();
//形参:operator new 分配内存失败时要调用的出错处理函数的指针,返回值:没调用之前就已经在起作用的旧的出错处理函数的指针
new_handler set_new_handler(new_handler p)throw();
};
int main(int argc,char *argv[])
{
cout<<"STL源码剖析:第二章 空间配置器"<<endl;
cout<<"空间不一定是内存,也可以是磁盘"<<endl;
cout<<"第一回合:设计一个简单的空间配置器"<<endl;
int ia [10] = {9,8,7,6,5,4,3,2,1,0};
vector<int ,MaChao::MaAllocator<int> > vecInt(ia,ia+10);
for(unsigned i=0;i<vecInt.size();i++)
{
cout<<vecInt.at(i)<<"\t";
}
getchar();
return 0;
}