SGI特殊的空間配置器: std::alloc
一般而言,我們所習慣的的C++記憶體配置操作和釋放操作是這樣的:
class Foo {…};
Foo* pf=new Foo;//配置記憶體,然後構造對象
delete pf; //将對象析構,然後釋放記憶體
其中new算式内含兩階段操作:
1.調用 ::operator new 配置記憶體;
template <class T>
inline T* allocate(ptrdiff_t size,T*){
set_new_handler();//set_new_handler的傳回值是一個函數指針,該函數指針指向調用 set_new_handler之前的異常處理函數,參數設定為0,表示空的。如果參數不為0,則會抛出異常
T* tmp=(T*)(::operator new((size_t)size*sizeof(T))));
if(tmp==){
cerr<<"out of memory"<<endl;
exit();
}
return tmp;
}
2.調用 Foo::Foo()構造對象内容
#include<new.h>//欲使用placement new 需要包含此檔案
template<class T1,class T2>
inline void construct(T1* p , const T2& value){
new (p) T1(value);//将初值設定到指針所指的空間上
}
其中delete算式内含兩階段操作:
1.調用 Foo::~Foo()将對象析構;
//以下是destroy()第一版本,接受一個指針
template <class T>
inline void destroy(T* pointer){
pointer->~T();将該指針所指之物析構掉
}
//以下是destroy()第二版本,接受兩個疊代器,此函數設法找出元素的數值型别
//進而利用_type_traits<>求取最适當措施
template <class ForwardIterator>
inline void destroy(ForwardIterator first,ForwardIterator last){
_destroy(first,last,value_type(first));
}
//判斷元素的數值型别(value type)是否有trivial destructor
template <class ForwardIterator,class T>
inline void_destroy(ForwardIterator first,ForwarIterrator last,T*){
typedef typename _type_traits<T>::has_trivial_destructor trivial_destructor;
_destroy_aux(first,last,trivial_destructor());
}
//如果元素的數值型别(value_type)有non-trivial destructor
template <class ForwardIterator>
inline void _destroy_aux(ForwardIterator first,ForwardIterator last,_false_type){
for( ;first<last;++first)
{
destroy(&*first);
}
}
//如果元素的數值型别(value_type)有trivial destructor
template <class ForwardIterator>
inline void_destroy_aux(ForwardIterator,ForwardIterator,_true_type){}
destroy()有兩個版本,第一個版本接受一個指針,準備将該指針所指之物析構掉,直接調用該對象的析構函數即可。第二個版本接受first和last兩個疊代器,準備将(first,last)範圍内所有對象析構掉,我們不知道這個範圍多大,萬一很大,而每個對象的析構函數都無關痛癢(即trivial destructor),那麼一次次調用這些無關痛癢的析構函數,對效率是一種傷害。是以,這裡首先利用value_type()獲得疊代器所指對象的型别,再利用_type_traits來判斷型别的析構函數是否無關痛癢。若是(true_type),則什麼也不做就結束;若不是無關痛癢的(_false_type),這才以循環方式巡訪整個範圍,并在循環中每經曆一個對象就調用第一個版本的destroy()。
2.調用 ::operator delete釋放記憶體;
template <class T>
inline void deallocate(T* buffer){
::operator delete(buffer);
}
為了精密分工,STL allocator決定就将這兩階段操作區分開來
1.記憶體配置操作由alloc::allocate()負責,記憶體釋放由alloc::deallocate()負責
2.對象構造操作由 ::construct()負責,對象析構操作由 ::destroy()操作
STL标準規格告訴我們,配置器定義于之中,SGI 内含一下兩個檔案:
#include<stl_alloc.h> //負責記憶體空間的配置與釋放
#include<stl_construct.h> //負責對象内容的構造與析構