2009-09-29 54 views
2

我需要創建一個對象池來消除動態分配。使用std :: stack來包含分配對象的指針是否有效?我可以使用std :: stack作爲對象池容器嗎?

我懷疑每次將釋放的對象推回堆棧時,都會動態分配一個新的堆棧元素。我對嗎?我應該使用std :: vector來確保沒有分配新東西嗎?

回答

4

一個堆棧是否適合您的特定目的是一個我不會涉及的問題。現在,如果您擔心分配數量,std :: stack的默認內部容器是std :: deque <>。它不需要在每次推送時爲堆棧分配新的內存(只要它有空間),並且當它分配它時不需要將所有現有的元素重新定位爲std :: vector <>。

你可以告訴堆棧使用的std ::矢量<>爲基礎容器與第二個模板參數:指針

std::stack< int, std::vector<int> > vector_stack; 
2

STL容器不符合它們指向的對象做任何事情,這取決於你,所以你有責任不泄漏任何內存等。看看Boost Pointer Container Library或嘗試存儲實際的對象,你將長期保存自己的麻煩。

如果你想減少由容器製作動態分配的金額,你知道你需要大概多少對象存儲,您可以使用矢量的「儲備()」方法,這將預分配您請求的內存一槍。

您也可以在構造函數中指定想要的記錄數,但這種方式會爲您創建x個對象,然後存儲它們,這可能不是您想要的。

如果出於某種技術原因動態分配完全沒有,您可能想嘗試使用boost::pool作爲您的分配器(如您所知,如果您不想使用默認值,則可以指定不同的std庫內存分配器一)。

這就是說,當我測試它時,默認的是總是加快,至少在g ++中是這樣的,所以它可能不值得這樣做。確保你描述它,而不是假設你可以編寫標準委託書。

0

任何在免費期間分配是錯誤由於不保證。如果你必須做一個免費的alloc,並且alloc拋出你在哪裏放置指針?您或者悄悄地捕獲異常並泄漏或傳播異常。傳播異常意味着使用您的YourObject不能放入STL容器中的對象。泄漏就是漏水。無論哪種情況,您都違反了規則。

但是,使用哪種數據結構取決於您的對象生存期控制方式。

是對成語與一個工廠的方法(或多個)和freeInstance

YourObject* pO = YourObject::getInstance(... reinitialize parameters ...); 
......object public lifetime.... 
pO->freeInstance(); 

或存儲器池被使用的對象池與一類特定的操作者新的/操作者用來刪除(或分配器) ?

YourObject::operator new(size_t); 
......object public lifetime.... 
delete pO; 

如果它是一個對象池,並有相關的發佈的代碼和雙端隊列或優選爲圓形緩衝器YourObject *的使用向量的數量的想法(如雙端隊列沒有儲備所以必須添加這在調試代碼中作爲動態自調整大小的循環緩衝區正是您想要的),並保留近似數字。在調試中分配釋放和FIFO中的LIFO,以便在調試中有歷史記錄。

在路那裏有沒有免費的對象,記得做reserve(nMade+1)YourObject*收集之前動態創建一個對象。

(這個儲備的原因是兩倍,首先,它必須在createInstance時間完成第二,它簡化了代碼,否則你有可能在freeInstance中投擲一個std :: badalloc,這可能會使析構保證很難保證。OUCH!例如 - Y類有一個YourObject*在其中併爲其YourObject*在其析構函數中執行freeInstance - 如果您不保留空間用於YourObject *當您將它存儲在哪裏存儲該指針時在freeInstance時間?如果您在getInstance之後預留空間,則必須捕獲std :: badalloc作爲儲備,釋放剛製作的YourObjectrethrow。)

如果它是一個內存池,然後在內存塊中使用發佈和雙向鏈接列表中的調試(我假設sizeof(YourObject)>=2*sizeof(void*))順便說一句,有很多的MemoryPool實現在那裏。在調試中再次分配釋放和FIFO中的LIFO,以便在調試中有歷史記錄。

順便說一句,如果您使用工廠成語不要跳過重載的getIntances()並添加reinit方法。這只是開放了一個重新呼叫的可能性。 getInstance方法是您的「構造函數」,意思就是說它是將對象轉換爲您想要的狀態。請注意,在對象池情況下,您需要一個freeInstance,它可能必須對對象執行「析構函數」操作。

在這種情況下,它有一定道理可言「公共類不變量」和「私有類不變量」的 - 對象坐在一個明朗狀態,其中公共類不變量可以得到滿足,而在空閒池。它的YourObject就像是一個YourObject,但所有的公共類不變式都可能不被滿足。 YourObject :: getInstance的作用是既獲得一個實例,又確保它的公有變量得到滿足。以一種補充的方式freeInstance釋放可能已經被getInstance獲取以確保「公共類不變量」得到滿足的資源可以在空閒列表上的對象「空閒時間」期間被釋放。在發佈

LIFO還具有高速緩存,其中的FIFO保證最後使用的對象/塊不緩存,如果有足夠多的對象/塊的重大利益 - 甚至頁面如果該號碼更大!但是當你決定使用堆棧時,你可能已經意識到了這一點。

強大的文本

+0

>>在免費做任何allocs是錯誤的,由於拋出異常,擔保。<< 它是如何連接到我的問題嗎? >>在調試代碼中使用已釋放代碼中的向量和最好是循環緩衝區<< 爲什麼? – jackhab 2009-09-30 12:12:39

+0

RE如何:釋放期間的alloc是否是vector或deque執行alloc - 如果該alloc失敗,您嘗試釋放的指針的位置在哪裏?我雖然這段話「這個儲備的原因是兩倍。」將問題解釋爲發生在Y析構函數中,該Y析構函數具有指向YourClass的指針 RE爲什麼:在調試模式下,FIFO分配會留下歷史記錄以便調試LIFO銷燬歷史記錄 – pgast 2009-12-30 12:00:16

相關問題