回答
通過接口引用相互引用的實例在基於引用計數的接口實現中彼此保持活動。
一個弱點是用來打破「彼此活着」的擁抱。這是通過將一個引用聲明爲一個純指針來繞過引用計數機制來完成的。
IFriend = Interface(IInterface)
end;
TFriend = class(TInterfacedObject, IFriend)
private
FFriend: IFriend;
end;
var
Peter: IFriend;
John: IFriend;
begin
Peter := TFriend.Create;
John := TFriend.Create;
Peter.Friend := John;
John.Friend := Peter;
end;
即使當彼得和約翰走出去的範圍,因爲它們之間的相互引用保持跌落至零的引用計數的情況下,圍繞保持。
問題是複合的模式更常見(父 - 子關係),其中孩子有一個反向引用父:
ISomething = Interface(IInterface)
end;
TSomething = class(TInterfacedObject, ISomething)
end;
TParent = class(TSomething)
FChildren: TInterfacedList;
end;
TChild = class(TSomething)
FParent: ISomething;
end;
再次,家長和孩子可以保持海誓山盟周圍,因爲它們之間的相互引用保持他們的計數降到零。
這解決了一個weak reference
:
TChild = class(TSomething)
FParent: Pointer;
end;
通過聲明FParent作爲一個「純粹」的指針引用計數機制沒有發揮作用的反向引用父。當父母超出範圍時,其引用計數現在可以降至零,因爲其孩子不再將其參考計數保持在零以上。
注意此解決方案確實需要對生命週期管理進行認真的關注。當這些課程「外部」的某些東西保持對兒童的引用時,孩子可以在父母的生活時間之外保持活力。當孩子假定父引用總是指向一個有效的實例時,這可能導致各種有趣的AV。如果您需要它,請確保當父對象超出範圍時,它將在它自己引用它的子對象之前讓它們的後備引用爲零。
默認情況下在Delphi中,所有引用或者是:
- weak references爲
pointer
和class
實例; - 明確的拷貝爲低電平值類型像
integer, Int64, currency, double
或record
(老棄用object
或shortstring
); - copy-on-write以reference counting爲高級值類型(例如,
string, widestring, variant
或動態陣列); - 強參考文獻參考數
interface
實例;
強引用計數的主要問題是潛在通知參考問題。當interface
對另一個有強烈的參考時,會發生這種情況,但目標interface
具有強回指向原始的指針。即使所有其他引用都被刪除,他們仍然會保持對方,並不會被釋放。這也可以通過鏈中最後一個引用回早期對象的對象鏈間接發生。
看到如下界面定義,例如:
IParent = interface
procedure SetChild(const Value: IChild);
function GetChild: IChild;
function HasChild: boolean;
property Child: IChild read GetChild write SetChild;
end;
IChild = interface
procedure SetParent(const Value: IParent);
function GetParent: IParent;
property Parent: IParent read GetParent write SetParent;
end;
下面的實現將決定性地導致內存泄漏:
procedure TParent.SetChild(const Value: IChild);
begin
FChild := Value;
end;
procedure TChild.SetParent(const Value: IParent);
begin
FParent := Value;
end;
在Delphi中,最常見的一種參考拷貝變量(即變種,動態數組或字符串)通過執行寫時複製來解決此問題。不幸的是,這種模式不適用於接口,它不是值對象,而是引用對象,綁定到一個實現類,它不能被複制。
注意,基於垃圾收集語言(如Java或C#)不存在這個問題,因爲循環引用是由它們的內存模型處理的:對象生命週期是由內存管理器在全球範圍保持不變。當然,它會增加內存使用量,由於分配和賦值期間的額外操作而導致進程減慢(所有對象及其引用都必須在內部列表中維護),並且可能在垃圾回收器進入操作時減慢應用程序速度。
沒有垃圾回收的語言(如Delphi)的一個常見解決方案是使用弱指針,通過該指針將接口分配給屬性而不增加引用計數。爲了輕鬆地創建一個弱指針,下面的函數可用於:
procedure SetWeak(aInterfaceField: PIInterface; const aValue: IInterface);
begin
PPointer(aInterfaceField)^ := Pointer(aValue);
end;
因此,可以作爲這樣的:
procedure TParent.SetChild(const Value: IChild);
begin
SetWeak(@FChild,Value);
end;
procedure TChild.SetParent(const Value: IParent);
begin
SetWeak(@FParent,Value);
end;
你可以嘗試讀取my blog post about weak references in Delphi - 及其相關的源代碼:我們實現了直接的弱引用,並將從Delphi 6到XE2的弱引用接口處理「歸零」。
事實上,在某些情況下,如果您將引用實例釋放到其子代之前,您需要將接口弱域設置爲nil
,以避免任何訪問衝突問題。這叫做「歸零弱指針」,以及我們試圖在Delphi中實現的什麼Apple implemented with the ARC model。
C#也有一個[WeakReference的(http://msdn.microsoft.com/de-de /library/system.weakreference.aspx)類來允許GC在沒有其他引用時清除該對象。 – 2012-07-16 16:37:23
@StefanGlienke你是對的,但在GC世界中,弱引用有點多種多樣,因爲它們是用來繞過垃圾集合本身的特定類。在Delphi中,我們沒有任何GC旁路,只是對管理自己內存的對象的引用。 (Zeroing)Delphi接口中的弱指針比這個要低一些。 – 2012-07-17 05:29:02
同意,我只想指出,這不僅僅是一個德爾福問題,雖然GC處理交叉/循環引用更聰明。 – 2012-07-17 05:49:11
在最常見的情況下,strong reference
控制引用實例的生命週期,而weak reference
則不控制引用實例的生命週期。術語weak reference
可用於垃圾回收器,引用計數接口或通用對象的上下文中。
例如,一個Delphi窗體包含對其所有控件的引用;這些引用可以被稱爲強壯的,因爲當表單被銷燬時,它的控件也被銷燬。另一方面,Delphi表單的控件有一個它所屬的表單的引用。這個引用可能會被調用爲弱,因爲它不以任何方式控制表單的生命週期。
又見
Automatic Reference Counting in Delphi Mobile Compilers
,其中包括新的[weak]
屬性的文件:
爲ARC的另一個重要概念是,你可以通過標記它們創建弱引用的角色, 具有[弱]屬性。
感謝您的分享。 – menjaraz 2013-05-22 09:48:52
- 1. 弱參考與Autofac解決?
- 2. ConcurrentHash地圖與弱參考
- 3. 我需要所有C標準函數的參考和解釋
- 4. 爲什麼需要幾次gc才能找到弱參考?
- 5. 短弱參考和長弱參考之間有什麼區別?
- 6. 需要參考本體的實例
- 7. 陣列參考解釋
- 8. 需要了解實體框架參考狀態
- 9. 需要解釋pcnt_fork()
- 10. CrudRepository解釋需要
- 11. 需要解釋MPI_Scatter()
- 12. 腳踏實地地介紹程序員的時間序列
- 13. 參考地址 - 等距地區的英語解釋
- 14. 需要Syncfusion.OcrProcessor.Base.dll裝配參考
- 15. 是否需要System.Web.Silverlight參考?
- 16. Xamarin需要參考Windows.Foundation.FoundationContract
- 17. 理解幻影參考VS相對於弱引用參考隊列
- 18. 解釋的「CA1800:不要不必要地投」需要
- 19. 瞭解弱地圖
- 20. 錯誤地解決參考
- 21. 需要對flask.request的解釋
- 22. 需要有人解釋.SelectedIndex
- 23. 需要Mysql死鎖解釋
- 24. 邏輯的解釋需要
- 25. 硒 - find_element_by_name需要解釋
- 26. keybd_event KEYEVENTF_EXTENDEDKEY解釋需要
- 27. python基本解釋需要
- 28. Python代碼解釋需要
- 29. JavaScript原型解釋需要
- 30. VHDL語法解釋需要
+1的解釋和您的個人資料圖片 – 2012-07-16 10:25:54
@JanDoggen::-)動物一直是我最喜歡的布偶 – 2012-07-16 11:29:04