空间适配器(allocator)
STL的操作对象(所有的数值)都存放在容器之内, 而容器一定需要配置空间以置放资料,所以这时需要到空间适配器。
1.空间配置器的标准接口
根据STL的规范,以下是allocator的必要接口:
allocator::value_type
allocator::pointer
allocator::const_pointer
allocator::reference
allocator::const_reference
allocator::size_type
allocator::difference_type
allocator::rebind
//一个嵌套的(nested) class template,class rebind<U>拥有唯一成员other, 那是一个typedef, 代表allocator<U>
allocator:: allocator()
default constructor
allocator::allocator(const allocator&)
copy constructor
template <class U>allocator::allocator(const allocator<U>&)
泛化的copy constructor allocaLor:: ~allocator ()
default constructor
pointer allocator::address(reference x) const
返回某个对象的地址。算式a.address(x)等同于&x
const_pointer allocator::address(const_reference x) const
返回某个const对象的地址。算式a.address(x)等同与&x
pointer allocator::allocate(size_type n, cosnt void*= 0)
配置空间,足以存储n个T对象.第二参数是个提示。实现上可能会利用它来增进区域性(locality) , 或完全忽略之
void allocator: :deallocate(pointer p, size_type n)
归还先前配置的空间
size_type allocator::max_size().const
返回可成功配置的最大量
void allocator: :construct(pointer p, const T& x)
等同于new(const void*) p) T(x)
void allocator: :destroy(pointer p)
等同于p->~T()
1.1 简单的空间配置器,JJ::allocator
#include<new>
#include<cstddef>
#include<cstdlib>
#include<climits>
#include<iostream>
#include<vector>
using namespace std;
namespace JJ
{
template <class T>
inline T* _allocate(ptrdiff_t size, T*)
{
set_new_handler(0);
T* tmp = (T*)(::new_handler new((size_t)(size * sizeof(T))));
if (tmp == 0)
{
cerr << "out of memory" << endl;
exit(1);
}
return tmp;
}
template <class T>
inline void _deallocate(T* buffer) {
::operator delete(buffer);
}
template <class T1,class T2>
inline void _deallocate(T* buffer) {
::operator delete(buffer);
}
template <class T1,class T2>
inline void _construct(T1* p, const T2& value) {
new(p) T1(value);
}
template <class>
inline allocator(T* ptr) {
ptr->~T();
}
template <class T>
class allocator {
public:
typedef T
typedef T*
typedef const T*
typedef T&
typedef const T&
typedef size_t
typedef ptrdiff_t
typedef <class U>
struct rebind {
typedef allocator<U> other;
};
pointer allocator(size_type n, const coid* 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(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));
}
};
}
//JJ::allocator应用于程序之中,只能有限度搭配PJ STL和RW STL
int main()
{
int ia[5] = {
0,1,2,3,4 };
unsigned int i;
vector<int, JJ::allocator<int> >iv(ia, ia + 5);
for (i = 0; i < iv.size(); i++)
cout << iv[i] << ' ' << endl;
}
2.具备次配置力(sub-allocation)的SGI空间配置器
SGI STL的配詈器与众不同, 也与标准规范不同, 其名称是alloc而非allocator, 而且不接受任何参数。换句话说,如果你要在程序中明白采用SGI配置器,则不能采用标准写法:
vector<int,std::allocator<int> >iv;//in VC or CB
必须这样写:
vector<int,std::alloc> iv;//in GCC
SGI STL allocator未能符合标准规格,不会带来困扰,因为通常我们使用缺省的空间配置器,很少需要自行指定配置器名称,而SGI STL的 每一个容器都已经指定其缺省的空间配置器为alloc。 例如下面的vector声明:
template <class T, class Alloc=alloc> //缺省使用alloc为配置器
class vector {
... };
2.1 SGI标准的空间配宣器, std ::allocator
SGI也定义有一个符合部分标准、 名为allocator的配置器,不建议使用。 主要原因是效率低, 只把C++的::operator new和::operator delete做一层薄薄的包装而已。下面是SGI的std::allocator全貌:
G++ 2.91.57, cygnus\cygwin-b20\include\g++\defalloc.h完整列表
//我们不赞成包含此文件。这是原始的HP default allocator。提供它只是为了
//回溯兼容
//
// DO NOT USE THIS FILE 不要使用这个文件,除非你手上的容器是以旧式做法
//完成一—那就需要一个拥有HP-style interface的空间配置器。SGI STL使用
//不同的allocator接口。SGI-style allocators不带有任何与对象型别相关
//的参数; 它们只响应void* 指针(侯捷注: 如果是标准接口, 就会响应一个
// "指向对象型别 的指针,T*)。 此文件并不包含于其它任何SGI STL头文件
#include <new.h>
#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
#include <iostream.h>
#include <algobase.h>
template <class T>
inline T* allocate(ptrdiff_t size, T*) {
set_new_handler(O);
T* tmp = (T*) (::operator new ((size_t) (size * sizeof (T)))) ;
if (tmp == 0) {
cerr << "out of memory" << endl;
exit (1);
}
return tmp;
}
template <class T>
inline void deallocate(T* buffer){
::operator delete