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