2.空間配置器
2.1具備次配置力(sub-allocation)的SGI空間配置器
SGI含有兩個空間配置器類填硕,std::allocator內(nèi)存分配類符合標準麦萤,但是僅僅是對operator new和operator delete簡單封裝一下而已;其次是SGI特殊的內(nèi)存分配器std::alloc,其中實現(xiàn)采用了內(nèi)存池扁眯,對于分配大量小容量的對象壮莹,可以大大減少內(nèi)存碎片。
SGI標準的空間配置器std::allocator
這是對應的模板內(nèi)聯(lián)內(nèi)存分配函數(shù)恋拍。實現(xiàn)起來也很簡單垛孔,注意這里分配的內(nèi)存僅僅是一塊沒有使用的空間而已,在上面并沒有構(gòu)造對象施敢,后面講解如何在上面構(gòu)造對象周荐。
模板內(nèi)聯(lián)內(nèi)存釋放函數(shù),直接調(diào)用全局的operator delete釋放對應的內(nèi)存僵娃。
SGI特殊的空間配置器Std::alloc
class Foo{…}
Foo* pf = new Foo;//配置內(nèi)存概作,然后構(gòu)造對象
delete pf;//將對象析構(gòu),然后釋放內(nèi)存
new的算是包含兩個階段:
1)? 調(diào)用::operator new 配置內(nèi)存
2)? 調(diào)用Foo::Foo()構(gòu)造對象內(nèi)容
Delete算式也包含兩個階段
1)? 調(diào)用Foo::~Foo()將對象析構(gòu)
2)調(diào)用::operator delete釋放內(nèi)存
為了精密分工默怨,STL allocator將兩個階段的操作分開來讯榕,內(nèi)存配置操作由alloc::allocate()負責,內(nèi)存釋放操作由alloc::deallocate()負責;對象構(gòu)造由::construct()負責愚屁,對象析構(gòu)由::destroy()負責济竹。
2.stl_alloc.h 內(nèi)存空間的分配和釋放
內(nèi)部使用malloc在堆中申請內(nèi)存,其中制造了一個內(nèi)存池霎槐,可以減少小型區(qū)塊過多而造成的內(nèi)存碎片問題送浊。
SGI設計了雙層級配置器,第一級配置器直接使用malloc()和free()丘跌,第二級配置器則視情況采用不同的策略:當配置區(qū)塊超過128bytes時袭景,采用第一級配置器,當配置區(qū)塊小于128bytes時闭树,采用第二級配置器耸棒,采用復雜的memory pool。它內(nèi)存池實際上就是內(nèi)部維護了16個自由鏈表报辱,預先已經(jīng)分配好了与殃,當需要從內(nèi)存池中取內(nèi)存時候,直接從對應鏈表取出即可捏肢;當釋放內(nèi)存到內(nèi)存池時候奈籽,直接將內(nèi)存插入鏈表即可。每個鏈表中節(jié)點分別占用8鸵赫、16衣屏、24、32辩棒、40狼忱、48、52一睁、64钻弄、72、80者吁、88窘俺、96、104复凳、112瘤泪、120、128字節(jié)育八。
舉例:
2.2 內(nèi)存操作全局函數(shù)
1对途、uninitialized_copy
將迭代器[first ,
last)范圍內(nèi)的內(nèi)容拷貝到result指定的區(qū)域。如果first是char 或wchar 那么直接使用memmove拷貝即可髓棋,如果first不是上述類型实檀,則通過辨別是否是POD類型來選擇構(gòu)造函數(shù)或者copy拷貝惶洲。
uninitialized_copy使我們能夠?qū)?nèi)存的配置和對象的構(gòu)造行為分離。
2膳犹、uninitialized_fill
將[first , last)迭代器指定范圍的內(nèi)存恬吕,通過x初始化。換句話說镣奋,該函數(shù)會針對操作范圍內(nèi)的每個迭代器i币呵,調(diào)用construct(&*I,x),在i所指之處產(chǎn)生x的復制品。與uninitialied_copy()一樣侨颈,該函數(shù)具備“commit or rollback”語義,要么產(chǎn)生所有必要元素芯义,要么不產(chǎn)生任何元素哈垢。如果任何一個copy constructor丟出異常(exception),該函數(shù)能夠?qū)⒁旬a(chǎn)生的所有元素析構(gòu)掉扛拨。
3耘分、uninitialized_fill_n
將[first , first+n)范圍內(nèi)的每一個迭代器都設定為x,總共設定了n個绑警,當是pod類型求泰,則直接拷貝x到指定的迭代器,不是pod類型计盒,那么在每一個迭代器上以x為初值進行構(gòu)造渴频。
上述是uninitialized_fill_n對應的簡單函數(shù)調(diào)用關系,重點在于理解POD類型北启。POD意思就是Plain
Old Data卜朗,也就是標量類型以及傳統(tǒng)的C struct類型。POD類型必須含有無用的構(gòu)造函數(shù)咕村、析構(gòu)函數(shù)场钉、拷貝構(gòu)造、賦值運算符函數(shù)懈涛。因此堆POD類型可以直接進行字節(jié)拷貝初始化逛万,而非POD類型采用最安全的做法,也就是通過對應的構(gòu)造函數(shù)初始化批钠。
總結(jié)圖:三個內(nèi)存基本函數(shù)的泛型版本與特化版本