STL原始碼剖析 讀書筆記(1)

2021-09-25 15:15:18 字數 1395 閱讀 7586

stl即c++標準模板庫,主要由六大部件組成,分別是:分配器、容器、迭代器、演算法、仿函式、介面卡。

在講述這些主要部件之前,先來了解一下物件導向程式設計和泛型程式設計,物件導向程式設計(object-oriented programming,簡稱oop)企圖將資料和處理資料的方法放到一起,例如,在c++的類中,一般會有成員變數和處理成員變數的成員函式,在需要使用的時候建立乙個物件,然後以物件來呼叫它們。而泛型程式設計(generic programming,簡稱gp)是將資料和處理方法分離開來,這裡的處理方法通常是全域性函式,例如stl中的演算法和容器,兩者互不影響,需要的時候通過迭代器來傳遞資訊。

好了,接下來就從這六大部件出發,了解stl的內部關係。這篇博文主要記錄分配器的重點。

allocator主要是用來管理儲存空間,它當中的 allocate() 呼叫 operator new() 來分配空間,其中 operator new() 中又呼叫了c語言中的 malloc() 函式,而 deallocate() 則呼叫了operator delete(),其中,operator delete() 又呼叫了 free() 來釋放記憶體。以上談的這種分配器是標準規範下的實現方法。而sgi stl有一種預設的分配器 alloc ,它的每乙個容器都已經指定其預設的空間分配器為 alloc,例如下面的 vector 宣告:

template

class vector;

這其中就是預設使用的 alloc 為分配器。由於呼叫 malloc() 只會尋找整片比較大的空間,對於一些小型區塊,可能造成記憶體浪費的問題,因此,sgi設計了雙級分配器,第一級分配器直接使用 malloc() 和 free(),第二級分配器則視情況採用不同的策略:當配置區塊超過128位元組時,視之為 「足夠大」,便呼叫第一級分配器 ,當分配區塊小於128位元組時,視之為 「過小」,為了降低額外負擔(合理利用資源),就使用第二級分配器。

而第二級分配器的具體實現是以記憶體池管理的形式,每次配置一塊大記憶體,然後維護對應的自由鍊錶(可增加,也可刪減),下次如果再有相同大小的記憶體需求,就直接從自由鍊錶中取出,如果使用方釋放了小塊記憶體,則由分配器**到對應的鍊錶中。為了方便管理,sgi的第二級分配器會主動將任何小額區塊的記憶體需求上調至8的倍數(例如使用者需要30位元組,就自動調整為32位元組),並維護16個自由鍊錶,各自管理的大小分別為:8,16,24,32,40,56,64,72,80,88,96,104,112,128位元組的小額區塊。

因此,整個的記憶體分配釋放過程即可歸納為如下流程:分配器擁有標準介面函式 allocate(),此函式首先判斷區塊的大小,大於128位元組就呼叫第一級分配器,小於128位元組就檢查對應的自由鍊錶。如果自由鍊錶內有可用的區塊,就直接拿來用,如果沒有可用的區塊,就將區塊大小上調至8的倍數,然後重新填充空間。 在釋放的時候,同樣由分配器的標準介面函式 deallocate() 首先判斷區塊大小,大於128位元組就呼叫第一級分配器,小於128位元組就找出對應的自由鍊錶,將區塊**。

STL原始碼剖析讀書筆記

一.stl提供六大元件,彼此可以組合套用。1.容器 containers 各種儲存結構,如vector list deque set map,用來存放資料。2.演算法 algorithme 各種常用演算法,如sort search copy erase等。3.迭代器 iterators 扮演容器與演...

《STL原始碼剖析》讀書筆記 三

hashtable 非標準 二叉搜尋樹 任何節點最多只能允許兩個子節點 平衡二叉樹 確保整棵樹的深度為o logn 左右子樹的高度最多差1 setmap multiset 特性與用法與set完全相同,唯一的差別在於它允許鍵值重複,插入的時候用的是rb tree的insert equal 而不是ins...

《STL原始碼剖析》讀書筆記 四

在stl中,所有的元素都是存放在容器中,容器需要配置空間來儲存這些數值,因此需要用到空間配置器。記憶體池 chunk alloc的工作 從記憶體池中取空間給free list使用。if 記憶體池水量足夠 直接調出20個區塊給free list else if 記憶體池水量還足夠提供至少1個區塊 調出...