最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

C++編程知識:教你手寫C++內存池

2021-08-23 13:30 作者:C語言編程__Plus  | 我要投稿

引言

使用?new expression?為類的多個實例分配動態(tài)內存時,cookie導致內存利用率可能不高,此時我們通過實現(xiàn)類的?內存池?來降低overhead。從不成熟到巧妙優(yōu)化的內存池,得益于union的?分時復用?特性,內存利用率得到了提高。


原因

在實例化某個類的對象時(在heap而不是stack中),若不使用?array new?,則每次實例化時都要調用一次內存分配函數,類的每個實例在內存中都有上下兩個cookie,從而降低了內存的利用率。然而,?array new?也有?先天的缺陷?,即只能調用默認無參構造函數,這對于很多沒有提供無參構造函數的類來說是不合適的。

因此,我們可以對于一個沒有實例化的類第一次實例化時,先分配一大塊內存(內存池),這一大塊內存記錄在類中,只有上下兩個cookie,能夠容納多個實例。后續(xù)實例化時,若內存池中還有剩余內存,則不必申請內存分配,只在內存池中分配。內存回收時,將實例所占用的內存回收到內存池中。若內存池中無內存,則再申請分配大塊內存。

我們以鏈表的形式組織內存池,內存池中每個一個鏈表是一個小桶,這個桶中裝我們實例化的對象。

內存池鏈表的頭結點記錄在類中,即以class staic變量的形式存儲。組織形式如下:


實現(xiàn)代碼如下:

測試代碼如下:

其結果如下:


可以看到每個?DemoClass?的實例大小為24字節(jié),內存池一次從操作系統(tǒng)中申請了576個字節(jié)的內存,這些內存可以容納24個實例。上面顯示出了每個實例的內存地址,內存池中相鄰實例的內存首地址之差為24,即實例的大小,證明了一個內存池的實例之間確實沒有cookie。

當內存池中內存用完后,又向操作系統(tǒng)申請了576個字節(jié)的內存。

由此,只有每個內存池兩側有cookie,而內存池中的實例不存在cookie,相比于每次調用?new expression?實例化對象都有cookie,內存池的組織形式確實在?形式上提高了內存利用率?。

那么,有什么問題么?

sizeof(DemoClass)?等于?24?:

int data數據域占4個字節(jié)

兩個構造函數一個析構函數各占4字節(jié),共12字節(jié)

額外的指針DemoClass*,在64位機器上,占8個字節(jié)

這樣一個?DemoClass?的大小確實是24字節(jié)。wait,?what??

我們?yōu)榱私鉀Qcookie帶來的內存浪費,引入了指針next,但卻又引入了8個字節(jié)的overhead,脫褲子放屁,?多此一舉??

這樣看來確實沒有達到要求,但至少為我們提供了一種思路,不是么?

分時復用改進方案

首先我們先回憶下c++ 中的?Union?:

在任意時刻,聯(lián)合中只能有一個數據成員可以有值。當給聯(lián)合中某個成員賦值之后,該聯(lián)合中的其它成員就變成未定義狀態(tài)了。

結合我們之前不成熟的內存池,我們發(fā)現(xiàn),當內存池中的桶還沒有被分配給實例時,只有next域有用,而當桶被分配給實例后,next域就沒什么用了;當桶被回收時,數據域變無用而next指針又需要用到。這不?正是?union?的特性?么?

看一下代碼實現(xiàn):

對比前一種實現(xiàn)代碼,只是構造函數、數據域和指針域的組織形式發(fā)生了變化:

由于數據域增加了price項,構造函數中也增加了對應的參數

數據域被集成定義成一個類自定義struct類型

數據域和指針域被組織為union

測試代碼依舊:

結果:


可以看到每個?DemoClass?的實例大小為24字節(jié),一個內存池的實例之間沒有cookie。

分析一下?sizeof(DemoClass)?等于?24?的緣由:

data數據域占12個字節(jié)(int 4字節(jié)、double 8字節(jié))。

兩個構造函數一個析構函數各占4字節(jié),共12字節(jié)。

指針DemoClass?,在64位機器上,占8個字節(jié),但由于和數據域使用了union,data數據域12個字節(jié)中的前8個字節(jié)在適當的時機被看作DemoClass?,而不占用額外空間,消除了overhead。

這樣一個?DemoClass?的大小確實是24字節(jié)。利用union的?分時復用?特性,我們消除了初步方案中指針帶來的脫褲子放屁效果。

另外的思考

細心的讀者可能會發(fā)現(xiàn),前面的那兩種方案都有共同的小缺陷,即當程序一直實例化而不析構時,內存池會向操作系統(tǒng)申請多次大塊內存,而當這些對象一起回收時,內存池中的剩余桶數會遠大于設定的POOL_SIZE的大小,這個峰值多大取決于類實例化和回收的時機。

另外,內存池中的內存暫時不會回收給操作系統(tǒng),峰值很大可能會對內存分配帶來一些影響,不過這卻不屬于內存泄漏。在以后的文章中,我們可能會討論一些性能更好的內存分配方案。

另外,對于準備學習編程的小伙伴,如果你想更好的提升你的編程核心能力(內功)不妨從現(xiàn)在開始!

微信公眾號:C語言編程學習基地

整理分享(多年學習的源碼、項目實戰(zhàn)視頻、項目筆記,基礎入門教程)

歡迎轉行和學習編程的伙伴,利用更多的資料學習成長比自己琢磨更快哦!



C++編程知識:教你手寫C++內存池的評論 (共 條)

分享到微博請遵守國家法律
左云县| 林州市| 莒南县| 巴林右旗| 潍坊市| 南汇区| 拉萨市| 波密县| 偃师市| 桂林市| 祁东县| 荆州市| 通榆县| 肃宁县| 五原县| 宝清县| 满城县| 舟曲县| 姚安县| 商水县| 都匀市| 东山县| 新源县| 汕头市| 塘沽区| 南丹县| 郎溪县| 大名县| 鞍山市| 上思县| 宁蒗| 东宁县| 会昌县| 剑阁县| 娱乐| 赣州市| 漯河市| 外汇| 长治县| 新竹县| 海林市|