STL——空間配置器

STL有6大組件:容器、算法、迭代器、仿函數、配接器、分配器。它們之間的密切關係是STL的精髓所在,容器用來存放數據,而容器存在的前提是要有分配器給它分配內存,接下來需要實現算法,迭代器便作爲算法來對容器數據操作的橋樑,算法可以使用仿函數完成不同的策略變化,配接器可修飾或套接仿函數。

說了麼辣麼多,所有種種始於存在的內存,說清分配器的來龍去脈看來是必不可少嘍。本文僅討論SGI STL的空間配置器。

1. 兩級配置器

要說的明白就不能囉嗦,術語定義也不需要,用到了再說。

只需要知道,new一般做了兩件事:分配內存與構造對象(delete反之),STL中將這兩個階段分開了!是的,它不再調用new來分配內存,二是調用c式的malloc幹活,這樣使得:內存的配置由alloc::allocator()負責(alloc是SGI STL的配置器,其它版本STL採用的配置器是allocator),內存釋放由alloc::deallocator()負責,對象的構造和析構由全局函數::constructor和::destroy負責。兩個分開了!

先看看構造與析構

構造::constuctor接受一個指針p和一個初值value,將初值設定到指針所指的空間上,定義如下:

    //這裏使用的是placement new,需要包含頭文件<new.h>
    //爲什麼是這樣的寫法,new會開闢新空間,所以不會在想要的地方初始化數據,而這裏的new是placement new,在p所指地址初始化值即可
    template <class T1, class T2>
    inline void constructor(T1 *p, const T2 & value) {
        new (p) T1(value);          
    }

析構::destroy有兩個版本,一個接受指針,可直接析構之;另一個接受first和last迭代器的版本,這時要分兩種情形:判斷元素的數值型別(value type)是否有trival destructor,如果是則什麼都不做,否則就逐個析構,這樣可以提高效率。

問題來了,什麼是value type?什麼又是trival destructor?
暫且這麼來理解,如果元素是int型,根本就不需要調用析構函數,所以value type判斷該元素型別是int,其具有trival destructor(沒什麼卵用的析構),那麼不需要逐個調用析構函數了,豈不是很清爽!對於複雜對象(要分配空間)的型別,其destructor當然是non_trival。

空間配置和釋放

重要的事情再說一遍:SGI以malloc()和free()完成內存配置與釋放。爲了簡潔,只說配置,不說釋放。

爲了儘量減少小型區塊造成內存碎片的問題,STI設計了雙層配置器,這兩級的處理關係如下:
如果定義了__USE_MALLOC則alloc爲第一級配置器,否則爲第二級。

  1. 第一級配置器會根據需求分配內存(malloc()),不夠用時調用oom_malloc()(這個會一直嘗試從堆中獲取區塊for(;;))。
  2. 第二級配置器首先判斷所需區塊大小是否大於128bytes,是則調用第一級配置器,否轉3。
  3. 從freelist中找(8字節對齊)對應區塊,有則返回之,並調整freelist,否轉4。
  4. 現在freelist中對應區塊不夠用,那麼調用refill函數,默認從memory pool(內存池)中chunk_alloc()20個同等大小的新區塊掛到freelist上,不過不夠20個,但夠1個,就拔出這不足20個的區塊給freelist,如果1個都不夠啦,就需要調用malloc從heap中配置內存,爲內存池注入活水。

問題又來了:什麼是freelist?
自由鏈表,SGI中定義的是freelist[16],分別指向塊大小爲(i+1)*8bytes 的內存區,然後相同大小的區塊會形成一個鏈表,有點類似與鄰接表這種數據結構。

2. 內存的基本處理工具

STL定義的5個全局函數:constructor()、destroy()、uninitialized_copy()、uninitialized_fill()、uninitialized_fill_n()。

後三個函數是的內存配置與對象構造行爲分離開來,copy是將未初始化的輸出去初始化爲對應的輸入去數據;fill是對區間內每個迭代器都初始化爲給定值x,fill_n將區間起始處後n個迭代器初始化爲x。

三者具體實現步驟: 判斷value_type是否爲POD, 是則調用fill_n(直接賦值),否則調用構造函數。

問題來了,什麼是POD?
POD指Plain Old Data,該型別數據擁有trival ctor/dtor/copy/assignment函數,簡單的也可以理解爲int。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章