STL 空間配置器

2021-07-04 13:06:08 字數 2131 閱讀 9310

stl有6大元件:容器、演算法、迭代器、仿函式、配接器、分配器。它們之間的密切關係是stl的精髓所在,容器用來存放資料,而容器存在的前提是要有分配器給它分配記憶體,接下來需要實現演算法,迭代器便作為演算法來對容器資料操作的橋梁,演算法可以使用仿函式完成不同的策略變化,配接器可修飾或套接仿函式。

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

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

只需要知道,new一般做了兩件事:分配記憶體與構造物件(delete反之),stl中將這兩個階段分開了!是的,它不再呼叫new來分配記憶體,二是呼叫c式的malloc幹活,這樣使得:記憶體的配置由alloc::allocator()負責(alloc是sgi stl的配置器,其它版本stl採用的配置器是allocator),記憶體釋放由alloc::deallocator()負責,物件的構造和析構由全域性函式::constructor和::destroy負責。兩個分開了!

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

//這裡使用的是placement new,需要包含標頭檔案

//為什麼是這樣的寫法,new會開闢新空間,所以不會在想要的地方初始化資料,而這裡的new是placement new,在p所指位址初始化值即可

template

inline void constructor

(t1 *p, const t2 & 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為第一級配置器,否則為第二級。

第一級配置器會根據需求分配記憶體(malloc()),不夠用時呼叫oom_malloc()(這個會一直嘗試從堆中獲取區塊for(;;))。

第二級配置器首先判斷所需區塊大小是否大於128bytes,是則呼叫第一級配置器,否轉3。

從freelist中找(8位元組對齊)對應區塊,有則返回之,並調整freelist,否轉4。

現在freelist中對應區塊不夠用,那麼呼叫refill函式,預設從memory pool(記憶體池)中chunk_alloc()20個同等大小的新區塊掛到freelist上,不過不夠20個,但夠1個,就拔出這不足20個的區塊給freelist,如果1個都不夠啦,就需要呼叫malloc從heap中配置記憶體,為記憶體池注入活水。

問題又來了:什麼是freelist?

自由鍊錶,sgi中定義的是freelist[16],分別指向塊大小為(i+1)*8bytes 的記憶體區,然後相同大小的區塊會形成乙個鍊錶,有點類似與鄰接表這種資料結構。

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。

STL 空間配置器

stl空間配置器的底層原理 維護了乙個狹義的記憶體池,並且用乙個自由鍊錶來維護該記憶體池。該自由鍊錶比較類似於雜湊的開鏈法的儲存結構。源 pragma once using namespace std define throw bad alloc cerr out of memory endl ex...

STL空間配置器

一級空間配置器 ifndef malloc alloc template h define malloc alloc template h if 0 include define throw bad alloc throw bad alloc elif defined throw bad alloc...

STL 空間配置器

stl的記憶體分配和釋放被詳細區分為四個部分 記憶體配置由allocate 負責 內部實現為operator new 記憶體釋放由deallocate 負責 內部實現為operator delete 物件構造由construct 負責 內部實現為placement new 物件析構操作由destro...