C 十六 記憶體池之鏈隊記憶體池的實現

2021-10-08 09:48:00 字數 3848 閱讀 6632

用new和malloc開闢記憶體時,記憶體是硬體資源,需要經過核心態,分配好後給使用者態。這個過程很麻煩,浪費時間,效率差。現在就想到了,一次性分配一大塊記憶體空間給應用程式,應用程式對其進行管理,這樣只有在第一次分配的時候經過核心,其他時候都是從應用程式管理的記憶體上取,釋放,這就是記憶體的自主管理機制。

引入兩個概念;

資源的集合;池中申請資源,最後返回給池;實現了資源的迴圈利用

把分配的一大塊記憶體稱為記憶體池:記憶體的集合。

通過什麼辦法進行記憶體池的操作呢?可以使用c++new開闢記憶體,delete釋放記憶體。

new:

delete:

那麼我們可以對new和delete進行過載,原來的new,delete是從系統上開闢,釋放記憶體,通過過載,實現new分配記憶體池上的資源,delete將資源釋放給記憶體池。

過載new,delete關鍵字函式和malloc,free函式原型一樣:

void* operator new(size_t size);

void operator delete(void* ptr);

記憶體池可以通過new,delete來操作,但是如何表示這大塊記憶體,如何實現new分配,delete**的功能?

【1. 記憶體碎片】

在使用系統記憶體資源時,會經常發生記憶體碎片的問題:

內碎片:申請了8位元組,但實際只用5位元組,浪費了3位元組,這就是內碎片。

外碎片:乙個小記憶體塊卡在兩個大記憶體塊之間,無法被分配。

使用系統的new和malloc不僅會導致記憶體使用效率低,還會產生外碎片問題。所以我們有了記憶體池,

讓系統一次性分配大塊記憶體,大記憶體不容易產生記憶體碎,但是我們必須對其進行管理,這樣才知道,下一次從哪個位置分配。所以要對記憶體池進行一定的管理:

選擇乙個合適的資料結構來儲存這一大塊記憶體,並可以進行管理,我們選擇靜態鍊錶。

【2.靜態鍊錶】

靜態鍊錶是以陣列的形式存在,做鍊錶的處理,有:

struct  node

靜態鍊錶會犧牲0號下標的空間,作為未分配出去的鍊錶的頭結點。犧牲最後乙個下標的空間,作為已分配出去的頭結點。如下圖所示:

【3. 儲存記憶體池的資料結構】

可以用優化後的靜態鍊錶儲存記憶體池,我們對靜態鍊錶進行一定的優化:

未分配結點:靜態鍊錶需要將0下標犧牲,我們可以定義不帶頭節點的單鏈表,用乙個指標指向這塊記憶體即可。對其進行優化,這樣可以使用的記憶體空間增多。

已分配結點:靜態鍊錶需要通過乙個鍊錶結點進行統一管理。但是在記憶體池中,我們是將記憶體分配給乙個變數使用,如:int* p=new int;記憶體釋放時,釋放p即可。所以不用進行統一的管理,因為有外部變數在管理。

所以記憶體池的資料結構是優化的靜態鍊錶:

以隊列為基礎,實現乙個鏈隊:入隊:new結點;出隊:delete結點;以模板方式是實現。

鏈隊由兩個類構成:結點類,和管理結點類

【(一) 結點類】

成員變數包含資料域,指標域

建構函式,將結點資料放入,指標指向null。

需要申請、釋放結點,成員方法有過載的new,delete函式。表示在結點類中需要對記憶體池進行管理

定義指向記憶體池的靜態指標。需要所有物件都可以看見,所以是靜態的。

【1. 生成乙個結點】

生成node_count大小的記憶體池,從記憶體池中獲取,釋放結點記憶體。

生成的記憶體池如下:

void * operator new(size_t size)//過載關鍵字new,實現記憶體池的開闢,分配一塊記憶體存放結點

pcur->pnext=null;//記憶體池最後乙個結點為null

} void* ptr=pool;

pool=pool->pnext;

return ptr;

}

【2. 刪除乙個結點】把分配的結點**到記憶體池中。

void operator delete(void* ptr)//過載關鍵字delete,將分配的結點插入記憶體池

【(二) 鏈隊類】成員變數:定義隊頭,隊尾指標指向結點。

【1. 建構函式】

建構函式生成乙個結點,此時new呼叫我們過載的new函式,此時獲得的頭節點是鏈隊的頭結點,記憶體池沒有頭結點:

【2. 析構】刪除所有的結點,迴圈刪除,這時的delete呼叫的是自己的寫的。

~queue()//迴圈刪除每個結點,呼叫自己寫的,即將每個結點還給記憶體池

phead=null;

}

【3. 入隊push】

void push(t val)//隊尾入隊

【4. 出隊】

void pop()//隊頭出隊

node* pcur=phead->pnext;

phead->pnext=pcur->pnext;

delete pcur;//這時呼叫的是我們過載的delete,將結點還給記憶體池

}

【5. 獲取隊尾】獲取隊尾指標指向結點的資料即可。

t back()//獲取隊尾元素

return ptail->mdata;

【6. 獲取隊頭】獲取隊頭指標指向結點的資料即可。

t front()//獲取隊頭

return phead->mdata;

}

整合得到完整**,執行結果如下:

實現了鏈隊的記憶體池,每一次分配,釋放結點,都是在分配的一大塊記憶體上獲取的。

加油哦!?。

記憶體池 C 記憶體池

c c 下記憶體管理是讓幾乎每乙個程式設計師頭疼的問題,分配足夠的記憶體 追蹤記憶體的分配 在不需要的時候釋放記憶體 這個任務相當複雜。1.呼叫malloc new,系統需要根據 最先匹配 最優匹配 或其他演算法在記憶體空閒塊表中查詢一塊空閒記憶體,呼叫free delete,系統可能需要合併空閒記...

記憶體池 簡單的記憶體池的實現

當頻繁地用malloc申請記憶體,然後再用free釋放記憶體時,會存在兩個主要問題。第乙個問題是頻繁的分配釋放記憶體可能導致系統記憶體碎片過多 第二個問題是分配釋放記憶體花費的時間可能比較多 這個問題不太明顯 這個時候我們就可以考慮使用記憶體池了。最樸素的記憶體池思想就是,首先你向系統申請一塊很大的...

C 記憶體池的實現

file memorypool.h note hangzhou hikvision system technology co.ltd.all right reserved.brief windows下記憶體池的實現 author zhangpeng nj 163.com date 11 15 201...