第2章 空間配接器(allocator)

第2章 空間配接器(allocator)

SGI STL的配置器與標準規範不同,其名稱是alloc而非allocator,而且不接受任何參數。雖然SGI也定義一個符合部分標準、名爲allocator的配置器,但SGI自己未使用它,也不建議使用。主要原因是效率不佳,只把C++的::operator new和::operator delete做一層包裝。

因此,在程序中:
vector<int, std::allocator<int> > iv;   //in VC
vector<int, std::alloc> iv;             //in GCC

1 SGI特殊的空間配置器,std::alloc

一般而言,對於C++內存配置操作和釋放操作

class Foo {...}
Foo *pf = new Foo;
delete pf;

這其中的new算式內包含兩階段操作:

(1)調用 ::operator new 配置內存;(2)調用Foo::Foo()構造對象內容。

delate算式也內含兩階段操作:

(1)調用Foo::~Foo()將對象析構;(2)調用 ::operator delete 釋放內存。

爲了精密分工:STL alloctor決定將兩階段操作區分開來。配置器定義在<memory>之中,包含以下兩個頭文件:

#include <stl_alloc.h> —內存配置 alloc::allocate() 負責,內存釋放 alloc::deallocate() 負責;

#include <stl_construct.h> —對象構造 ::construct() 負責,對象析構 ::destroy() 負責。

該頭文件中定義了全局函數construct()和destroy(),負責對象的構造和析構。

T1 *pT1 = new(p) T1(value);  //在p所指的內存空間中 構造一個新T1類的實例。即placement new.
注:如果你想在預分配的內存上創建對象,用缺省的new操作符是行不通的。要解決這個問題,你可以用placement   new構造。它允許你構造一個新對象到預分配的內存上。

2 對象的構造與析構

construct()和destroy()這兩個作爲構造和析構只用的函數被設計爲全局函數,,符合STL規範。此外,STL還規定配置器必須擁有名爲construct()和destroy()的兩個成員函數,然而真正在SGI STL中的名爲std::alloc的配置器並未遵守這一規則。

3 空間的配置與釋放(內存的配置與釋放),std::alloc

對象構造前的空間配置和對象析構後的空間釋放,由<stl_alloc.h>負責。

C++內存配置基本操作是::operator new(),內存釋放的基本操作是::operator delete()。這兩個全局函數相當於C的malloc()和free()函數。SGI正是以malloc()和free()完成內存的配置與釋放。

考慮小型區塊可能造成的內存破碎問題,SGI設計了雙層級配置器:

第一級配置器__malloc_alloc_template,直接使用malloc()和free();

第二級配置器__default_alloc_template,SGI第二級配置器的做法是,如果區塊夠大,超過128bytes時,就移交第一級配置器處理。當區塊小於128bytes時,則以內存池(memory pool)管理。內存池以malloc()配置而得。如果內存不足,轉調用第一級配置器。

此法又稱之爲次層配置(sub-allocation):每次配置一大塊內存,並維護對應之自由鏈表(free-list)。爲了方便管理,SGI第二級配置器會主動將任何小額區塊的內存需求量上調至8的倍數,並維護16個free-lists,各自管理大小分別爲8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128 bytes的小額區塊。

注:配置器本質是一個模板類,而且:

typedef __malloc_alloc_template alloc
typedef __default_alloc_template alloc

4 空間配置函數allocate()、空間釋放函數deallocate()

①配置器_default_alloc_template擁有配置器的標準接口函數allocate()。此函數首先判斷區塊的大小,大於128bytes就調用第一級配置器,小於128bytes就檢查對應的free list。如果free list之內有可用的區塊,就直接拿來用,如果沒有可用區塊,就將區塊大小上調至8倍數邊界,然後調用refill(),準備爲free list重新填充空間。新的空間將取自內存池(經由chunk_alloc()完成)。缺省取得20個新節點(新區塊),萬一內存池空間不夠,獲得的節點數可能小於20。

②配置器__default_alloc_template擁有配置器標準接口函數deallocate()。該函數首先判斷區塊大小,大於128bytes就調用第一級配置器,小於128bytes就找對應的free list,將區塊回收。

5 內存基本處理工具

STL定義有五個全局函數,作用於未初始化空間上。

1. construct()
2. destroy()
3. uninitialized_copy()
4. uninitialized_fill()
5. uninitialized_fill_n()

其中,使用下面三個低層次函數,應該包含<memory>,不過SGI把他們實際定義在<stl_uninitialized>

發佈了54 篇原創文章 · 獲贊 14 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章