Delphi XE10.1 引用计数,Delphi XE10.1 Berlin终于增加了对接口的Weak, UnSafe的支持

以往的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;

procedureTForm1.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

procedureDoSomething;

procedureAddObjectRef (simple: ISimpleInterface);

end;

TObjectOne =class(TInterfacedObject, ISimpleInterface)

private

anotherObj: ISimpleInterface;

public

procedureDoSomething;

procedureAddObjectRef (simple: ISimpleInterface);

end;

.....................

procedureTObjectOne.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;

procedureTForm1.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

procedureTForm1.Button2Click(Sender: TObject);

var

[unsafe] one: ISomeInterface;

begin

one := TSomeObject.Create;

one.DoSomething;

end;

  

https://www.cnblogs.com/hezihang/p/5536928.html#undefined