STL的內(nèi)存分配與traits技巧
在《STL原碼剖析》一書中詳細分析了SGI STL的內(nèi)存分配器的行為。與直接使用new operator不同的是,SGI STL并不依賴C++默認的內(nèi)存分配方式,而是使用一套自行實現(xiàn)的方案。首先SGI STL將可用內(nèi)存整塊的分配,使之成為當(dāng)前進程可用的內(nèi)存,當(dāng)程序中確實需要分配內(nèi)存時,先從這些已請求好的大內(nèi)存塊中嘗試取得內(nèi)存,如果失敗的話再嘗試 整塊的分配大內(nèi)存。這種做法有效的避免了大量內(nèi)存碎片的出現(xiàn),提高了內(nèi)存管理效率。
為了實現(xiàn)這種方式,STL使用了placement new,通過在自己管理的內(nèi)存空間上使用placement new來構(gòu)造對象,以達到原有new operator所具有的功能。
template
inline void construct(T1* p, const T2& value)
{
new(p) T1(value);
}
此函數(shù)接收一個已構(gòu)造的對象,通過拷貝構(gòu)造的方式在給定的內(nèi)存地址p上構(gòu)造一個新對 象,代碼中后半截T1(value)便是placement new語法中調(diào)用構(gòu)造函數(shù)的寫法,如果傳入的對象value正是所要求的類型T1,那么這里就相當(dāng)于調(diào)用拷貝構(gòu)造函數(shù)。類似的,因使用了 placement new,編譯器不會自動產(chǎn)生調(diào)用析構(gòu)函數(shù)的代碼,需要手工的實現(xiàn):
template
inline void destory(T* pointer)
{
pointer->~T();
}
與此同時,STL中還有一個接收兩個迭代器的destory版本,可將某容器上指定范 圍內(nèi)的對象全部銷毀。典型的實現(xiàn)方式就是通過一個循環(huán)來對此范圍內(nèi)的對象逐一調(diào)用析構(gòu)函數(shù)。如果所傳入的對象是非簡單類型,這樣做是必要的,但如果傳入的 是簡單類型,或者根本沒有必要調(diào)用析構(gòu)函數(shù)的自定義類型(例如只包含數(shù)個int成員的結(jié)構(gòu)體),那么再逐一調(diào)用析構(gòu)函數(shù)是沒有必要的,也浪費了時間。為 此,STL使用了一種稱為“type traits”的技巧,在編譯器就判斷出所傳入的類型是否需要調(diào)用析構(gòu)函數(shù):
template
inline void destory(ForwardIterator first, ForwardIterator last)
{
__destory(first, last, value_type(first));
}
其中value_type()用于取出迭代器所指向的對象的類型信息,于是:
template
inline void __destory(ForwardIterator first, ForwardIterator last, T*)
{
typedef typename __type_traits
__destory_aux(first, last, trivial_destructor());
}
//如果需要調(diào)用析構(gòu)函數(shù):
template
inline void __destory_aux(ForwardIterator first, ForwardIterator last, __false_type)
{
for(; first < last; ++first)
destory(&*first); //因first是迭代器,*first取出其真正內(nèi)容,然后再用&取地址
}
//如果不需要,就什么也不做:
tempalte
inline void __destory_aux(ForwardIterator first, ForwardIterator last, __true_type)
{}
相關(guān)推薦:計算機等級考試二級:C++學(xué)習(xí)重點分析試題北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |