STL 原始碼剖析allocator 深入(五)

2021-06-20 17:41:28 字數 3036 閱讀 1326

此時感悟:在夜深人靜的時候,感謝自己可以思考,可以成長。

今天在學校,看到了即將要來的招聘會,我知道,現在的自己必須面對現實,因為只有你得到了,才會留下來!

stl 原始碼剖析 第二章,比較詳細的簡述了allocator,我在上面一篇也有簡單的介紹!由於今天在看原始碼有很多 不解,所以特此來總結和學習。

標準allocator需要實現rebind,allocate,deallocate,max_size和構造及析構函式一共六個函式

我就對不常見的加以介紹吧!

vc原始碼 

templateclass _vector_val

有些vc原始碼 包含乙個基類

templateclass _vector_val: public _container_base

再看看下面的**

templateclass _vector_val

: public _container_base

{ // base class for vector to hold data

public:

typedef typename _alloc::template rebind<_ty>::other _alty;

可以看出是乙個模板類,那麼rebind 有什麼作用呢?

typedef

typename

_alloc::

template

rebind<_ty>::other _alty; 

整體來看是型別定義,假設現在我們這樣使用

vector, 那麼_ty 即 int, _ax 即 allocator,由vector 類傳遞給 基類

_vector_val,則_alloc 即

allocator

;可以看到 

allocator

是allocator 模板類的特化,

rebind<_ty> 

是成員模板類,other是成員模板類

中自定義

型別,_ty 即是int , 那麼other 型別也就是allocator

, 也就是說_alty 是型別 

allocator。

_alty _alval; 即 基類定義了乙個

allocator

型別的成員,被vector 繼承後以後用於為vector 裡面元素分配記憶體等操作。

alocator 是記憶體分配器,stl在這個層面上進行開放是為了讓使用者/程式設計師有權選擇不同的記憶體分配器。舉例來說,allocator_a和allocator_b在記憶體分配方式上可能是不一樣的,也就是說allocator_a和allocator_b所分配的記憶體很有可能是不一樣的。 

假如有乙個容器類myvector, 它用的是allocator_a記憶體分配器,這個容器類很有可能需要double型別的分配器,而且要求對int和double型別的記憶體分配策略是一樣的,這是rebind的意義就體現出來了。

總之一句話,rebind實現了對不同型別使用同一種記憶體分配策略的要求。

sgi的allocator首先接受使用者所需要的size_t,然後 呼叫allocate(其實是客戶端這麼寫objalloc.allocate(n);),allocate向 freelist(__de****t_malloc_template的乙個資料成員,型別為乙個obj* volalite freelist[16],既是儲存這16個列表的那個傢伙),如果freelist沒有記憶體(或者說它是空的,為初始化)那麼呼叫 refill,refill從真正的sig memory pool中取記憶體,取出做多20個客戶端所需要的size_t大小的記憶體塊,通過chunk_alloc,取出來後將其妝扮好(就是想這20塊記憶體連線為 乙個鍊錶),上交給allocate享用

template 

char*

__default_alloc_template<__threads, __inst>::_s_chunk_alloc(size_t __size,

int& __nobjs)

默 認情況下__nobjs實參為20,而且是乙個位址傳遞(引用傳遞).他做的工作可是相當相當的偉大.原始社會的時候,一切資源都相當的豐富(原始人從來 不擔心石油危機),chunk_alloc從記憶體裡面取出20塊size_t大小的記憶體上交給refill,refill將其裝配後,上交 freelist,allocate從freelist中取出一塊上交給我(^_^),其實是我想allocate要記憶體,結果沒有,allocate想 refill要記憶體,refill馬上把chunk_alloc找來,於是記憶體有了.

當然記憶體要節約使用,第一次我想要乙個32位元組的內 存,chunk_alloc找來了2*20*32個位元組的記憶體,其中的20塊上交給了refill,refill填充 freelist,freelist[3]儲存其中19個,上交給客戶端(我)乙個.下一次我要乙個8位元組的記憶體,chunk_alloc又要找記憶體了, 不過上次找來的記憶體還沒有用完(上次交了20*24,剩餘20*24,也就是剩餘480位元組),而且足夠上交refill的了(需要8*20=160), 他們我上交給他所需要的記憶體,不從系統堆(heap)裡面取用記憶體(只有chunk_alloc這樣的勞動人民知道花錢小心翼翼).這樣美好的日子一直持 續著,突然有一天,chunk_alloc發現系統記憶體重要用完了,怎麼辦?怎麼向refill交差?refill一再壓迫 chunk_alloc.chunk_alloc於是去找freelist,freelist內部儲存上尚未陪客戶端(client)取走的記憶體,比如 freelist[3],中還有10塊沒有用完,也就是說有160個位元組的記憶體,那麼chunk_alloc看看內不能滿足refill的最小需求(1塊 size_t),然後毫無保留的上交上去.如果連freelist都沒有記憶體了,chunk_alloc於是向同門兄弟 __malloc_default_alloc求助(呼叫它的allocate),再那裡有記憶體不足的處理情況,或許就要std::bad_alloc 了!

誠實的講sgi的策略已經是異常的完美了,但是作為乙個stl,只能是最完美的,其中還是存在一些不足,因為乙個完美的memory_pool實在是很有難度的!!

STL原始碼剖析 空間配置器(allocator)

一般容器都需要一定空間存放資料,allocator就是用來配置空間的,sgi的allocator配置的物件時記憶體。乙個allocator通常包含兩個部分,一是記憶體配置和記憶體釋放 allocate的deallocate 二是物件構造和析構 construct和destory ifndef jja...

stl原始碼剖析讀書筆記之allocator

第二章開始作者定義了乙個簡單的模板類jj allocator,有allocator的所有介面,包括allocator deallocate construct destroy 四個成員函式 但是開啟 stl原始碼中的stl alloc.h,sgi stl用的最多的std alloc並沒有constr...

STL原始碼剖析

這兩天略讀完了 stl原始碼剖析 之所以是略讀,就是只看大體,不講具現 這個詞在 深度探析c 物件模型 中比較多 已經看過好幾本c 的書了,感覺c 本身設計的博大精深,而c 編譯器就更是乙個神奇的東西,換句話說,你永遠不知道c 編譯器揹著你做了哪些出乎你意料的事 不扯遠了 我主要是想看stl容器的具...