深度剖析C++對(duì)象池自動(dòng)回收技術(shù)實(shí)現(xiàn)
摘要:對(duì)象池可以顯著提高性能,如果一個(gè)對(duì)象的創(chuàng)建非常耗時(shí)或非常昂貴,頻繁去創(chuàng)建的話會(huì)非常低效。本文將探討對(duì)象池的技術(shù)特性以及源碼實(shí)現(xiàn)。
對(duì)象池可以顯著提高性能,如果一個(gè)對(duì)象的創(chuàng)建非常耗時(shí)或非常昂貴,頻繁去創(chuàng)建的話會(huì)非常低效。對(duì)象池通過(guò)對(duì)象復(fù)用的方式來(lái)避免重復(fù)創(chuàng)建對(duì)象,它會(huì)事先創(chuàng)建一定數(shù)量的對(duì)象放到池中,當(dāng)用戶需要?jiǎng)?chuàng)建對(duì)象的時(shí)候,直接從對(duì)象池中獲取即可,用完對(duì)象之后再放回到對(duì)象池中,以便復(fù)用。這種方式避免了重復(fù)創(chuàng)建耗時(shí)或耗資源的大對(duì)象,大幅提高了程序性能。本文將探討對(duì)象池的技術(shù)特性以及源碼實(shí)現(xiàn)。
對(duì)象池類圖
ObjectPool:管理對(duì)象實(shí)例的pool。Client:使用者。
適用性:
類的實(shí)例可重用。類的實(shí)例化過(guò)程開(kāi)銷較大。類的實(shí)例化的頻率較高。
效果:
節(jié)省了創(chuàng)建類實(shí)例的開(kāi)銷。節(jié)省了創(chuàng)建類實(shí)例的時(shí)間。存儲(chǔ)空間隨著對(duì)象的增多而增大。
問(wèn)題?
目前縱觀主流語(yǔ)言的實(shí)現(xiàn)方式無(wú)外乎3個(gè)步驟:
初始創(chuàng)建一定數(shù)量的對(duì)象池(也允許從外面添加對(duì)象)。從對(duì)象池中取對(duì)象來(lái)使用。用完之后返回對(duì)象池。
一般情況下這樣是OK的,可能存在的問(wèn)題是在第三步,有兩個(gè)問(wèn)題:
不方便,每次都需要顯式回收對(duì)象。忘記將對(duì)象放回對(duì)象池,造成資源浪費(fèi)。
改進(jìn)動(dòng)機(jī)?
解決顯式回收的問(wèn)題,實(shí)現(xiàn)自動(dòng)回收,省心省力。改進(jìn)之后的對(duì)象池?zé)o須提供release方法,對(duì)象會(huì)自動(dòng)回收,改進(jìn)之后的類圖如下。
技術(shù)內(nèi)幕
借助c++11智能指針,因?yàn)橹悄苤羔樋梢宰远x刪除器,在智能指針釋放的時(shí)候會(huì)調(diào)用刪除器,在刪除器中我們將用完的對(duì)象重新放回對(duì)象池。思路比較簡(jiǎn)單,但實(shí)現(xiàn)的時(shí)候需要考慮兩個(gè)問(wèn)題:
什么時(shí)候定義刪除器?用shared_ptr還是unique_ptr??1. 什么時(shí)候定義刪除器
自定義刪除器只做一件事,就是將對(duì)象重新放入對(duì)象池。如果對(duì)象池初始化的時(shí)候就自定義刪除器的話,刪除器中的邏輯是將對(duì)象放回對(duì)象池,放回的時(shí)候無(wú)法再定義一個(gè)這樣的刪除器,所以這種做法行不通。需要注意,回收的對(duì)象只能是默認(rèn)刪除器的。除了前述原因之外,另外一個(gè)原因是對(duì)象池釋放的時(shí)候需要釋放所有的智能指針,釋放的時(shí)候如果存在自定義刪除器將會(huì)導(dǎo)致對(duì)象無(wú)法刪除。只有在get的時(shí)候定義刪除器才行,但是初始創(chuàng)建或加入的智能指針是默認(rèn)刪除器,所以我們需要把智能指針的默認(rèn)刪除器改為自定義刪除器。?
1.2 用shared_ptr還是unique_ptr
因?yàn)槲覀冃枰阎悄苤羔樀哪J(rèn)刪除器改為自定義刪除器,用shared_ptr會(huì)很不方便,因?yàn)槟銦o(wú)法直接將shared_ptr的刪除器修改為自定義刪除器,雖然你可以通過(guò)重新創(chuàng)建一個(gè)新對(duì)象,把原對(duì)象拷貝過(guò)來(lái)的做法來(lái)實(shí)現(xiàn),但是這樣做效率比較低。而unique_ptr由于是獨(dú)占語(yǔ)義,提供了一種簡(jiǎn)便的方法方法可以實(shí)現(xiàn)修改刪除器,所以用unique_ptr是最適合的。?
1.3 實(shí)現(xiàn)源碼
[cpp]?view plaincopy #pragma?once?? #include?