Delphi XE10.1 引用計數

 

以往的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;
相關文章
相關標籤/搜索