以往的Delphi版本,不支持接口的Weak,和UnSafe的引用,支持对象的Weak, UnSafe,而且仅在Android和Ios平台上支持。
现在Delphi XE10.1 Berlin终于增加了对接口的Weak, UnSafe的支持。
1.Weak
Weak引用,不影响引用计数器,但是如果对象被释放,Weak引用变量自动清0,来看例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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 ;
|
运行结果
1 2 |
Ptr: 16360080
Ptr: 0
|
weak引用非常适合用于两个对象需要互相引用的情况下,如果以往的引用,将无法让引用计数器清0.
如下面的例子,互相引用后,两个对象的计数器都不清0,导致内存泄漏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
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引用,来快速方便的解决泄漏问题:
1 2 |
private
[weak] anotherObj: ISimpleInterface;
|
2.UnSafe
unsafe引用,不影响引用计数,但不会向Weak引用那样清零引用的变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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 ;
|
运行结果
1 2 |
Ptr: 42640064
Ptr: 42640064
|
由于Unsafe引用,不影响应用计数器,下面的程序将导致内存泄漏:
1 2 3 4 5 6 7 |
procedure TForm1 . Button2Click(Sender: TObject);
var
[unsafe] one: ISomeInterface;
begin
one := TSomeObject . Create;
one . DoSomething;
end ;
|
https://www.cnblogs.com/hezihang/p/5536928.html#undefined