空間配置器隱藏在一切組件之后茄猫。
1.1 設(shè)計(jì)一個(gè)簡(jiǎn)單的空間配置器
- 根據(jù)STL的規(guī)范誊抛,以下是allocator的必要接口:
allocator::value_type
allocator::pointer
allocator::const_pointer
allocator::reference
allocator::const_reference
allocator::size_type
allocator::difference_type
allocator::rebind // 一個(gè)嵌套的(nested)class template列牺。class rebind<U>擁有唯一成員other,是一個(gè)typedef拗窃,代表alloctor<U>
allocator::allocator() // default constructor
allocator::allocator(const allocator&) // copy constructor
template <class U>allocator::allocator(const allocator<U>&) //泛化的default constructor
allocator::~allocator() // default constructor
pointer allocator::address(reference x) const // 返回某個(gè)對(duì)象的地址瞎领。a.address(x)等同于&x
const_pointer allocator::address(const_reference x) const // 返回某個(gè)const對(duì)象的地址。a.address(x)等同于&x
pointer allocator::allocate(size_type n, const void* = 0) // 配置空間随夸,足以存儲(chǔ)n個(gè)T對(duì)象九默。第二個(gè)參數(shù)是個(gè)提示,可能會(huì)用來(lái)增進(jìn)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.2 一個(gè)簡(jiǎn)單的allocator源代碼
// filename : qyalloc.h
#ifndef __QYALLOC__
#define __QYALLOC__
// placement new是operator new的一個(gè)重載版本驼修,只是我們很少用到它。如果你想在已經(jīng)分配的內(nèi)存中創(chuàng)建一個(gè)對(duì)象诈铛,使用new是不行的乙各。也就是說(shuō)placement new允許你在一個(gè)已經(jīng)分配好的內(nèi)存中(棧或堆中)構(gòu)造一個(gè)新的對(duì)象幢竹。原型中void*p實(shí)際上就是指向一個(gè)已經(jīng)分配好的內(nèi)存緩沖區(qū)的的首地址耳峦。
// placement new的作用就是:創(chuàng)建對(duì)象(調(diào)用該類的構(gòu)造函數(shù))但是不分配內(nèi)存,而是在已有的內(nèi)存塊上面創(chuàng)建對(duì)象妨退。用于需要反復(fù)創(chuàng)建并刪除的對(duì)象上妇萄,可以降低分配釋放內(nèi)存的性能消耗。請(qǐng)查閱placement new相關(guān)資料咬荷。
#include <new> // placement new 要包含此文件冠句,聲明了一個(gè)void *operator new( size_t, void *p ) throw() { return p; }
#include <cstddef> // for ptrdiff_t, size_t
#include <cstdlib> // for exit()
#include <climits> // for UINT_MAX
#include <iostream> // for cerr
namespace QY{
// 分配空間(operator new)
template <class T>
inline T* _allocate(ptrdiff_t size, T*){
std::set_new_handler(0);
T *tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
if (tmp == 0)
{
std::cerr << "out of memory" << std::endl;
exit(1);
}
return tmp;
}
// 回收空間(operator delete)
template <class T>
inline void _deallocate(T* buffer){
::operator delete(buffer);
}
// 在指定內(nèi)存上構(gòu)造一個(gè)對(duì)象(new(pMyClass)MyClass();)
template <class T1, class T2>
inline void _construct(T1* p, const T2& value){
new(p) T1(value); // 創(chuàng)建。placement new. 調(diào)用 ctor of T1, 即new(pMyClass)MyClass();
}
// 析構(gòu)對(duì)象
template<class T>
inline void _destroy(T* ptr){
ptr->~T();
}
// 按allocator標(biāo)準(zhǔn)幸乒,定義結(jié)構(gòu)
template <class T>
class allocator{
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;
// 重新綁定分配器(rebind allocator of type U)
template <class U>
struct rebind
{
typedef allocator<U> other;
};
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(reference x){
return (pointer)&x;
}
const_pointer address(const_reference x){
return (const_pointer)&x;
}
size_type max_size() const{
return size_type(UINT_MAX / sizeof(T));
}
};
} // end of namespace QY
#endif // __QYALLOC__
1.3 使用這個(gè)allocator
#include "qyalloc.h"
#include <vector>
#include <iostream>
using namespace std;
int main(){
int ia[5] = {0, 1, 2, 3, 4};
unsigned int i;
vector<int, QY::allocator<int> > iv(ia, ia+5);
for(i=0; i<iv.size(); i++)
cout << iv[i] << ' ';
cout << endl;
return 0;
}
1.4 SGI標(biāo)準(zhǔn)的空間配置器(std::allocator)
符合部分標(biāo)準(zhǔn)懦底,效率不佳,不建議使用罕扎。
1.5 SGI特殊的空間配置器(std::alloc)
class Foo{ ... };
Foo* pf = new Foo; // 配置內(nèi)存聚唐,然后構(gòu)造對(duì)象
delete pf; // 將對(duì)象析構(gòu)丐重,然后釋放內(nèi)存
new: (1)調(diào)用 ::operator new 配置內(nèi)存;
(2)調(diào)用 Foo::Foo() 構(gòu)造對(duì)象內(nèi)容杆查。
delete: (1)調(diào)用 Foo::~Foo() 將對(duì)象析構(gòu)扮惦;
(2)調(diào)用 ::operator delete 釋放內(nèi)存。
為了精密分工亲桦,STL allocator 將兩階段操作區(qū)分開(kāi)來(lái)崖蜜。
alloc::allocate()負(fù)責(zé)內(nèi)存配置操作;
alloc::deallocate()負(fù)責(zé)內(nèi)存釋放操作客峭;
::construct()負(fù)責(zé)對(duì)象構(gòu)造操作豫领;
::destroy()負(fù)責(zé)對(duì)象析構(gòu)操作。