2011-01-11 41 views
12

共享指針(例如boost :: shared_ptr或新的std :: shared_ptr)和垃圾收集方法(例如在Java或C#中實現的方法)之間有什麼區別?我理解它的方式是,共享指針記錄變量指向資源的次數,並在計數達到零時自動破壞資源。然而,我的理解是垃圾收集器也管理內存資源,但需要額外的資源來確定對象是否仍然被引用,並且不一定會立即破壞資源。垃圾收集與共享指針

我在我的假設中是否正確,並且在使用垃圾收集器和共享指針之間還有其他區別嗎?另外,爲什麼有人會使用垃圾收集器來處理共享指針,如果他們執行類似的任務,但具有不同的性能數據?

+1

使用共享指針**是一種垃圾收集技術。至少作爲第一步,許多垃圾收集器實施引用計數。 – 2011-01-11 22:29:25

回答

12

正如您所指出的,主要區別在於資源何時被釋放/銷燬。

GC可能派上用場的一個好處是如果你的資源需要很長時間才能發佈。對於短的程序生命週期,最好讓資源懸而未決並最終清理它們。如果達到資源限制,則GC可以採取行動釋放其中一些資源。另一方面,共享指針在引用計數達到零後立即釋放它們的資源。對於需要昂貴時間的資源的頻繁採集 - 釋放週期來說,這可能是昂貴的。另一方面,在一些垃圾收集實現中,垃圾收集要求整個程序暫停執行,同時檢查內存,移動並釋放內存。有更聰明的實現,但沒有一個是完美的。

15

那些共享指針(通常稱爲引用計數)存在循環風險。

垃圾收集(馬克和掃描)沒有這個問題。

+0

你能解釋一下「循環風險」是什麼意思嗎?你的意思是讓引用計數「環繞」,因爲用於保存引用計數的數據類型?或者是其他東西? – helloworld922 2011-01-11 22:59:29

+3

想象一下拿着一個ptr到B和B指向A. – 2011-01-11 23:03:33

0

在一個簡單的垃圾收集系統中,沒有人會持有指向任何對象的直接指針;相反,代碼將持有對指向堆上對象的表項的引用。堆中的每個對象都將存儲其大小(意味着所有堆對象將形成一個單鏈表),並在對象表中保存對象(或至少用於)的對象的反向引用。

當堆或對象表變滿時,系統將在表中的每個對象上設置一個「刪除我」標誌。它將檢查它所知道的每個對象,並且如果設置了它的「刪除標記」,則取消設置並將它知道的所有對象添加到要檢查的對象列表中。一旦完成,其「刪除我」標誌仍然設置的任何對象都可以被刪除。

一旦完成,系統將從堆的開始處開始,將每個對象存儲在那裏,並查看其對象引用是否仍然指向它。如果是這樣,它會將該對象複製到堆的開頭,或者剛過最後一個複製對象的末尾;否則該對象將被跳過(並且在其他對象被複制時可能會被覆蓋)。