以往的Delphi版本,不支持接口的Weak,和UnSafe的引用,支持對象的Weak, UnSafe,並且僅在Android和Ios平臺上支持。spa
如今Delphi XE10.1 Berlin終於增長了對接口的Weak, UnSafe的支持。orm
1.Weak對象
Weak引用,不影響引用計數器,可是若是對象被釋放,Weak引用變量自動清0,來看例子:blog
type TA=class(TInterfacedObject) end; procedure TForm1.Button1Click(Sender: TObject); var a:IInterface; [weak]aweak:IInterface; begin a:=TA.Create; //建立對象,複製給a,執行完成後引用計數器=1 aweak:=a; //因爲aweak定義有[weak]屬性,因此賦值給aweak後,引用計數器依舊爲1,但aweak變量的地址被保存到一個weak關聯列表中 Memo1.Lines.Add(Format('Ptr:%d', [NativeInt(Pointer(aweak))])); a:=nil; //因爲引用計數器=1,執行此句後,計數器清0,對象被釋放,同時與此對weak關聯列表中全部變量也被賦值爲nil,包括aweak變量. Memo1.Lines.Add(Format('Ptr:%d', [NativeInt(Pointer(aweak))])); end;
運行結果接口
Ptr:16360080 Ptr:0
weak引用很是適合用於兩個對象須要互相引用的狀況下,若是以往的引用,將沒法讓引用計數器清0.內存
以下面的例子,互相引用後,兩個對象的計數器都不清0,致使內存泄漏class
type ISimpleInterface = interface procedure DoSomething; procedure AddObjectRef (simple: ISimpleInterface); end; TObjectOne = class (TInterfacedObject, ISimpleInterface) private anotherObj: ISimpleInterface; public procedure DoSomething; procedure AddObjectRef (simple: ISimpleInterface); end; ..................... procedure TObjectOne.AddObjectRef (simple: ISimpleInterface); begin anotherObj:=simple; end; ..................... var one, two: ISimpleInterface; begin one := TObjectOne.Create; two := TObjectOne.Create; one.AddObjectRef (two); two.AddObjectRef (one);
這時候在Delphi XE10.1 Berlin下能夠用weak引用,來快速方便的解決泄漏問題:變量
private [weak] anotherObj: ISimpleInterface;
2.UnSafe內存泄漏
unsafe引用,不影響引用計數,但不會向Weak引用那樣清零引用的變量。引用
type TA=class(TInterfacedObject) end; procedure TForm1.Button2Click(Sender: TObject); var a:IInterface; [unsafe]aunsafe:IInterface; begin a:=TA.Create; aunsafe:=a; Memo1.Lines.Add(Format('Ptr:%d', [NativeInt(Pointer(aunsafe))])); a:=nil; Memo1.Lines.Add(Format('Ptr:%d', [NativeInt(Pointer(aunsafe))])); end;
運行結果
Ptr:42640064 Ptr:42640064
因爲Unsafe引用,不影響應用計數器,下面的程序將致使內存泄漏:
procedure TForm1.Button2Click(Sender: TObject); var [unsafe] one: ISomeInterface; begin one := TSomeObject.Create; one.DoSomething; end;