alloc不接受任何template型別引數,它只是乙個別名。
另外,new物件操作實際執行兩個過程:
1>呼叫::operator new 配置記憶體。
2>呼叫相應的建構函式,構造物件。
delete物件也執行兩個過程:
1> 呼叫相應的析構函式,析構物件。
2> 呼叫::operator delete 釋放記憶體。
為了精密分工,stl allocator將 兩個過程分開處理,配置記憶體alloc::allocate()負責,釋放記憶體alloc::deallocate()負責;該過程定義在檔案stl_alloc.h中;構造物件::construct()負責,析構物件::destory()負責,該過程定義在檔案stl_construct.h中。
construct()與destory()關鍵在於析構工具destory(),因為該工具用到了traits技巧_type_traits,除了_type_traits,還有iterator_traits,iterator_traits負責提取迭代器的特性,_type_traits負責提起類別的特性。這兩種traits貫穿整個stl,因此這裡著重介紹_type_traits。
_type_traits定義在檔案中
首先定義了兩種型別 _true_type 和 _false_type
struct __true_type ;
struct __false_type ;
然後,定義_type_traits的預設版本,預設型別都是_false_type
template struct __type_traits ;
然後定義 _type_traits的特化版本:_tp為特定型別時的版本。
stl分別特化了_tp為:bool,char, signed char ,unsigned char,wchar_t,short,unsigned short,int,unsigned int,long,unsigned long,long long,unsigned, long long,float,double,long double,char*,signed char*,unsigned char*,const char*,const signed char*,const unsigned char*的版本。這些版本的定義是相同的,都是將 _false_type 改為了 _true_type。說明這些型別都是pod型別的。以char型別為例,定義如下:
struct __type_traits;
destory()有兩個版本,第乙個是接收乙個指標型別引數的:這個沒什麼奧秘
templateinline void _destroy(_tp* __pointer)
另外乙個版本是接收兩個迭代器型別引數的,這個版本的奧秘在於用到了iteraotr_traits和_type_traits。
templateinline void _destory(forwarditerator first,forwarditerator last)
templateinline void _destory(forwarditerator first,forwarditerator ,last,t*)
//aux 是輔助的意思
//_destory_aux根據第三個引數的不同型別,有兩個版本
templateinline void _destory_aux(forwarditerator first,forwarditerator last,_false_type)
c++的記憶體配置基本操作是::operator new()與::operator delete()。這兩個全域性函式類似於c語言的malloc()與free()。stl用的是malloc()與free()完成記憶體的配置與釋放。因為c++並沒有提供類似c語言中realloc()的函式。
空間的配置與釋放定義在檔案中,主要需要考慮的問題是:
1> 應對記憶體不足的策略。
2> 解決小區域塊記憶體引起的「記憶體碎片」問題
為了解決「記憶體碎片問題」,stl採取的措施是 雙層配置器。至於只用一級配置器,還是兩個配置器都用 取決於是否定義_use_malloc。二級配置器的工作流程圖如下
另外乙個需要注意的是,配置單位的問題,malloc配置單位是byte,可將配置單位改為個別元素的大小(sizeof(t))
templateclass ******_alloc
static _tp* allocate(void)
static void deallocate(_tp* __p, size_t __n)
static void deallocate(_tp* __p)
};
1. 一級配置器
一級配置器直接使用malloc()與free()管理記憶體。使用malloc()而不是::operator new(),的原因是,c++並沒有提供類似c語言中realloc()的函式。
c++中有個c++ new _handler機制,可以要求系統在記憶體配置無法滿足時呼叫乙個你指定的函式。因為一級配置器中沒有用到::operator new()所以,不能用c++ 的set_new_handler()。解決方法是,仿造乙個功能類似的set_malloc_handler()。
先了解一下c++ new_handler機制
namespace std
函式指標typedef的用法
typedef
int(*myfun)
(int, int);
myfun是個函式指標,該函式型別為 輸入兩個int,輸出乙個int
2.二級配置器
當區域塊小於128bytes時,則以記憶體池(memory pool)管理。
原理是:
用16個free-list分別管理大小分別為8、16、24、32、40、48、56、64、72、80、88、96、104、112、120、128bytes的小區域塊。如果小區域塊大小不為上邊的16個大小,則上調至8的倍數,例如:25,則會上調至32,方法是:(n+7)& ~(7);
每次分配一大塊記憶體,由free-list維護,如果下次有相同大小的記憶體需求時,直接從free-list中取出。
解釋上圖:
剛開始客戶呼叫chunk_alloc(32,20) ,於是通過malloc配置40個32bytes的區域,第乙個交出,另19個交給free_list[3]維護,剩餘的20個給記憶體池;然後客戶呼叫chunk_alloc(64,20),此時free-list[7]為空,必須向記憶體池要記憶體,但是記憶體池只能提供(20*32)、64=10個64bytes的區塊,就將這10個區塊返回,乙個給客戶,剩餘9個由free_list[7]維護。此時記憶體池為空,然後客戶呼叫chunk_alloc(96,20),此時free_list[11]也為空,記憶體池也為空,於是用malloc()配置40+n(附加量)個96bytes的區塊,第乙個給客戶,另19個交個free_list[11]維護,剩餘的20+n個96bytes的區塊留給記憶體池。
STL學習 SGI二級空間配置器原始碼剖析
二級空間配置器 defaule alloc template 如果感覺光看 難以理解,可以看看上篇部落格介紹了二級空間配置器是怎樣進行記憶體分配的。enum 最小申請的空間的大小 enum 能最大申請的空間的大小 sgi第二配置器有16個free lists enum free lists的個數 t...
STL原始碼 特殊的空間配置器
源 展示 stl標準的空間配置器 就是將new和delete進行了簡單的封裝,這裡不是重點,就懶得說了。而且這個標準的空間配置器也沒被進行使用。sgi特殊的空間配置器 一級配置器的實現 就是正常的malloc和free,但在此的基礎上新增了乙個事件處理 即針對於malloc返回值為null的情況,系...
空間配置器
普通存放資料的原理 需要空間 new new 申請空間 構造物件 new是將malloc重新封裝的,使用一次malloc,在記憶體中除了會開闢所需空間外,還會額外開闢36個位元組 通過這種形式管理空間可以防止越界訪問 普通方式存放資料是存在缺陷的 1.頻繁的向系統索要小的記憶體塊,會產生記憶體碎片。...