一、 符合STL標準的空間配器接口c++
STL是c++中使用很是普遍的一個標準庫,它包含各類有用的容器。而空間配置器做爲STL各類容器的背後的核心,負責容器內部內存的分配和釋放。不過空間配置器能夠分配的也不僅是內存,由於空間也意味着能夠是磁盤或者其餘存儲介質。下邊是一個符合STL規範的空間配置器的必要接口:函數
allocator::value_type工具
allocator::pointer指針
allocator::const_pointer對象
allocator::reference接口
allocator::const_reference內存
allocator::size_typeast
allocator::difference_typeclass
//上邊這幾個都是一些typedef定義,其中 size_type 和difference_type是stddef.h中 size_t, ptrdiff_t這兩個類型的類型別名(ptrdiff_t是兩個指針相減的結果)效率
allocator::rebind
allocator::allocator
allocator::allocator(const allocator&)
template<class U>
allocator::allocator(const allocator(U)&)
//泛化的拷貝構造函數
allocator::~allocator()
pointer allocator::address(reference X) const
const_pointer allocator::address(const_reference X)const
pointer allocator::allocator(size_type n, const void* = 0)
void allocator::deallocate(pointer p, size_type n)
//歸還先前配置的空間
size_type allocator::max_size() const
void allocator::construct(pointer p, const T& x)
void allocator::destrory(pointer p)
二、 SGI空間配置器
SGI STL的配置器與標準規範不一樣,其名稱是alloc而不是allocator,並且不接受任何參數。若是在程序中須要明確使用SGI的配置器,咱們不能採用標準寫法:
vector<int, std::allocator<int> > v
須要這麼寫:
vector<int, std::alloc> v
一般狀況下,咱們使用的stl中的容器都是用標準配置器,而SGI STL的每個容器都已經指定其缺省空間配置器爲alloc,如:
template <class T, class Alloc=alloc>
class vector {…}
2.1 標準空間配置器
SGI STL也有一個符合標準,名爲allocator的配置器,但SGI從未使用過它,由於它效率過低,只是對::operator new, ::operator delete的簡單封裝而已;下邊我着重介紹SGI特殊的配置器alloc。
2.2 SGI特殊空間配置器, std::alloc
C++中,咱們在申請內存和釋放內存的時候,通常這樣作:
class Foo{}
Foo* f = new Foo
delete f
這其中new操做符內部含有兩階段操做,(1)調用new申請內存, (2)調用Foo:Foo()即對象的構造函數構造對象內容。
delete也含有兩段操做:(1)調用Foo::~Foo()將對象析構, (2) 調用delete 釋放內存。
爲了精密分工也更有效的利用內存,SGI alloc將這兩個階段分開來操做。內存配置有alloc::allocator()負責內存配置,alloc::deallocator()負責內存釋放;::constructor()負責構造對象;::destrory負責析構對象。
2.3內存配置後對象的構造與內存釋放前對象的析構工具: constructor()和destrory()
這兩個函數爲全局函數,符合stl規範。
constructor()接受一個指針p和一個初值,該函數的做用是將初值設定到指針所指的內存空間上
template<class T1, class T1>
inlie void destructor(T1 *p, const T2 &value) {
new (p) T1(value) //placement new 在一個已經分配的內存中建立對象
}
destroy()函數有兩個版本,一個版本接受一個指針參數,直接調用這個指針所指對象的析構函數析構對象。
template<class T>
inline void destroy(T* pointer){
pointer->~T();
}
另一個版本接受兩個迭代器,
template<class ForwardIterator, class T>
inline void destroy(ForwardIterator first, ForwardIterator last, T*) {
…
}
destroy函數實現的有點複雜,他先獲取到迭代器所指對象的的類型,而後在看對象是否有trivial destructor, 若是有,調用一個什麼也不作的版本;若是有non-trivial destructor,則遍歷迭代器中的每個對象,而後依次調用其析構函數。
(這裏主要是處於效率考慮, 若是一個對象的析構函數沒有任何做用,那麼循環調用這個函數對效率是一種傷害)。
備註:
什麼是trivial destructor呢?舉個例子來講,存在A,B兩個類,其中類B含有一個數據成員C,C有析構函數須要釋放一些內存;那麼在這種狀況下,A就含有trivial destructor, 而B則含有non-trivial destructor。