




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、內存池的主要作用,簡單地說來,便是提高內存的使用效率。堆內存的申請與釋放(new/delete及malloc/free),涉及復雜的內存分配算法,相比由簡單CPU指令支持的棧內存的申請與釋放,則是慢上了數量級。另一方面,棧的大小是有限制的,在需要大量內存的操作時,堆的使用是必要的。當然,頻繁地申請與釋放堆內存,效率是很低的,這也就是內存池出現(xiàn)的原因。類似std:vector容器,在向vector里添加一個元素之前,該容器往往提前申請了一大塊內存,實際添加時就只需要拿出其中一小塊來使用,不用每添加一個都使用new一次。內存池所做的,也就是一次申請一塊大內存,然后再小塊小塊地拿出來用:一次申請NM
2、大小的內存,必然比N次申請M大小的內存要快,這就是內存池高效的簡單解釋。一般來說,內存池可以按兩種維度劃分:單線程與多線程,可變大小和固定大小。其中最簡單的單線程固定大小的內存池。這類內存池只考慮單線程的程序,分配與回收的對象都是固定大小的。這個簡單的內存池類模板聲明如下: template<typename T, int BaseSize=32> class SimpleMemPool private: #pragma pack(push, 1) union ObjectChunk ObjectChunk * next; char bufsizeof(T); ; struct M
3、emBlock MemBlock* next; ObjectChunk chunksBaseSize; ; #pragma pack(pop) SimpleMemPool(const SimpleMemPool<T, BaseSize> &) ; MemBlock * head; ObjectChunk * freeChunk; public: SimpleMemPool(); SimpleMemPool(); T* New(); void Delete(T* t); ; template<typename T, int BaseSize=32>class Si
4、mpleMemPool private:#pragma pack(push, 1)union ObjectChunkObjectChunk * next;char bufsizeof(T);struct MemBlockMemBlock* next;ObjectChunk chunksBaseSize;#pragma pack(pop)SimpleMemPool(const SimpleMemPool<T, BaseSize> &) ;MemBlock * head;ObjectChunk * freeChunk;public:SimpleMemPool();SimpleM
5、emPool();T* New();void Delete(T* t); 該內存池類模板實例化之后,產生一個只用于申請對象T的內存池。創(chuàng)建對象的方法是T* New(),刪除對象的方法是void Delete(T *)。類模板中還定義了兩個數據結構及兩個成員變量,還禁止了內存池的拷貝構造。對于這種內存池,它有兩層的鏈表結構:第一層是內存塊鏈表(MemBlock),由成員head為頭,把內存池中申請的大塊內存串接起來。MemBlock結構的next指針指向了下一個內存塊,chunks則為BaseSize個ObjectChunk對象。該鏈表的每個結點都是內存池進行一次申請得到的大內存塊;第二層為自由
6、內存塊鏈表(ObjectChunk),由freeChunk為頭指針串著,該鏈表的每一個結點,都是一個可以使用的小內存塊。大體結構如下圖(BaseSize為5)所示:當用戶向內存池申請一個對象T時,內存池會檢查freeChunk是否為NULL。不為NULL時,表示還有自由的小內存塊(ObjectChunk)可供使用,將它返回給用戶,并將freeChunk移到下一個自由內存塊;若freeChunk為NULL,則內存池需要使用new/malloc從申請一塊大內存(MemBlock),然后將其中的BaseSize個ObjectChunk都串連上形成鏈表,再將freeChunk做為頭指針。這時freeC
7、hunk不為NULL了,可以提供給用戶一塊小內存了(具體即是,取出鏈表的首結點)。view plaincopy to clipboardprint?template<> class SimpleMemPool T* New() if (!freeChunk) MemBlock * t = new MemBlock; t->next = head; head = t; for(unsigned int i=0; i<BaseSize-1;+i) head->chunksi.next = & (head->chunksi+1); head->chu
8、nksBaseSize-1.next = 0; freeChunk = & (head->chunks0); ObjectChunk * t = freeChunk; freeChunk = freeChunk->next; return reinterpret_cast<T*>(t); ; template<>class SimpleMemPoolT* New()if (!freeChunk)MemBlock * t = new MemBlock;t->next = head;head = t;for(unsigned int i=0; i&
9、lt;BaseSize-1;+i)head->chunksi.next = & (head->chunksi+1);head->chunksBaseSize-1.next = 0;freeChunk = & (head->chunks0); ObjectChunk * t = freeChunk;freeChunk = freeChunk->next;return reinterpret_cast<T*>(t); 當用戶不再使用某塊小內存時,需要調用Delete方法。此時,內存池把用戶不用的小塊內存,重新連接到以freeChunk為首指
10、針的鏈表中就行了(將結點插入鏈表的首位置)。代碼如下:view plaincopy to clipboardprint?template<> class SimpleMemPool void Delete(T* t) ObjectChunk * chunk = reinterpret_cast<ObjectChunk*>(t); chunk->next= freeChunk; freeChunk = chunk; ; template<>class SimpleMemPoolvoid Delete(T* t)ObjectChunk * chunk =
11、reinterpret_cast<ObjectChunk*>(t);chunk->next= freeChunk;freeChunk = chunk; 當內存池不在使用時,析構釋放全部內存,此時只需要釋放head為首指針的鏈表的每個結點(遍歷刪除)。代碼如下:view plaincopy to clipboardprint?template<> class SimpleMemPool() SimpleMemPool() while(head) MemBlock * t = head; head = head->next; delete t; template
12、<>class SimpleMemPool()SimpleMemPool()while(head)MemBlock * t = head;head = head->next;delete t; 實現(xiàn)中,需要注意的是ObjectChunk的雙重身份:當它是自由內存塊,還未分配給用戶時,它是ObjectChunk的數據結構,包含一個鏈表指針,用于串連;當它分配給用戶時,它退出了自由內存塊鏈表,它被強制轉換為T類型(代碼中用了reinterpret_cast操作符號強制轉換),此時便不再有ObjectChunk里的數據,不再需要鏈表指針。所以ObjectChunk結構的大小,應該大
13、于或等于T類型的大?。ǔ霈F(xiàn)大于情況,是因為ObjectChunk最小也必須包含一個指針大小,而T類型卻小于一個指針大?。?。#pragma pack指令的使用,便是盡量使ObjectChunk的大小符合我們的預期(MemBlock也一樣)當用戶不再使用T類型對象時,便調用了Delete(T*),此時,T類型里的數據內容都不再重要了,強制變?yōu)镺bjectChunk后,把其內容覆蓋,使用前幾個字節(jié)作為指針,又加入自由內存鏈表中。總體說來,這個簡單的內存池,僅僅實現(xiàn)了一次(向系統(tǒng))申請,多次分配(給用戶)的功能。對于大內存塊(MemBlock),采取的方法是只申不放,僅在內存池銷毀時才一次性全部釋放。
14、這樣的策略僅僅適用于內存申請與釋放頻繁,且內存充足的情況。而多線程,可變大小的情況,也需要更多考慮。附完整代碼: template<typename T, int BaseSize=32> class SimpleMemPool private: #pragma pack(push, 1) union ObjectChunk ObjectChunk * next; char buf sizeof(T); ; struct MemBlock MemBlock* next; ObjectChunk chunksBaseSize; ; #pragma pack(pop) SimpleMe
15、mPool(const SimpleMemPool<T, BaseSize> &) MemBlock * head; ObjectChunk * freeChunk; public: SimpleMemPool() : head(0), freeChunk(0) SimpleMemPool() while(head) MemBlock * t = head; head = head->next; delete t; T* New() if (!freeChunk) MemBlock * t = new MemBlock; t->next = head; head = t; for(unsigned int i=0; i<BaseSize-1;+i) head->chunksi.next = & (head->chunksi+1); head->chunksBaseSize-1.next = 0; freeChunk = & (h
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 黔南2025年貴州黔南州龍里縣人民醫(yī)院(醫(yī)共體)總院招聘6人筆試歷年參考題庫附帶答案詳解
- 砂紙購銷合同范本
- 勞保物資回收合同范本
- 上海珠寶培訓課件
- 2025至2030年中國梅花彈片數據監(jiān)測研究報告
- 課題研究合同范本
- 建筑勞務培訓課件
- 托管接送的合同范本
- 產品制作培訓課件
- 2025年中國鐵塑桶市場調查研究報告
- 《人力資源管理》全套教學課件
- 空白房屋裝修合同范本
- GB/T 3452.3-2005液壓氣動用O形橡膠密封圈溝槽尺寸
- 數據結構英文教學課件:chapter2 Array
- 認識校園植物課件
- 大氣污染控制工程課程設計-某廠酸洗硫酸煙霧治理設施設計
- 外墻外保溫粘結強檢測PPT教案
- 信陽礦產資源概況
- 標準擊實試驗自動計算記錄表
- 一個近乎完美的微信引流招生方案
- 旅行社安全檢查記錄表
評論
0/150
提交評論