(delphi11最新学习资料) Object Pascal 学习笔记---第11章第1节 (Weak 和 Unsafe 类型接口引用)

11.1.4 Weak 和 Unsafe 类型接口引用

​ 从 Delphi 10.1 Berlin 开始,Object Pascal 语言对接口引用的管理进行了优化。实际上,Object Pascal 语言提供了不同类型的引用:

  • 常规引用在分配和释放时分别递增和递减对象引用计数,最终在引用计数为零时释放对象。

  • 弱引用(标有[weak]修饰符)不会增加所引用对象的引用计数。这些引用是完全可管理的,因此如果被引用对象被销毁,它们会被自动设置为nil。

  • 不安全引用(标有[unsafe]修饰符)不会增加其引用对象的引用计数,并且不受管理–这与基本指针没有太大区别。

    注解 弱引用和不安全引用的使用最初是作为移动平台 ARC 内存管理支持的一部分引入的。由于 ARC 现已淘汰,因此该功能仅适用于接口引用。

​ 通常引用计数在处于激活状态的情况下,你可以使用如下代码,该代码依赖引用计数来释放临时对象:

procedure TForm3.Button2Click(Sender: TObject);
var
   OneIntf: ISimpleInterface;
begin
   OneIntf := TObjectOne.Create;
   OneIntf.DoSomething;
end;

​ 如果对象有一个标准的引用计数实现,而您想创建一个不计入引用总数的接口引用,该怎么办?现在,您可以通过在接口变量声明中添加 [unsafe] 属性来实现这一目的,将上面的代码更改为:

procedure TForm3.Button2Click(Sender: TObject);
var
   [unsafe] OneIntf: ISimpleInterface;
begin
   OneIntf := TObjectOne.Create;
   OneIntf.DoSomething;
end;

​ 这并不是一个好主意,因为上述代码会导致内存泄漏。通过禁用引用计数,当变量离开作用域时,什么也不会发生。在某些情况下,这样做是有好处的,因为你仍然可以使用接口,而不会触发额外的引用。换句话说,不安全引用就像指针一样,不需要额外的编译器支持。
​ 现在,在你打算使用[unsafe] 属性而不增加引用计数的时候,请考虑一下,在大多数情况下,还有另一种更好的选择:使用弱(weak)引用。弱引用也可以避免增加引用计数,但它们是受管理的。这意味着系统会跟踪弱引用,如果实际对象被删除,系统会将弱引用设置为nil。相反,如果使用不安全引用,则无法知道目标对象的状态(这种情况称为悬挂引用)。

​ 弱引用在哪些情况下有用?一个典型的情况是两个对象相互引用。事实上,在这种情况下,该对象会武断地增加其他对象的引用计数,并导致对象基本上会永远被保留在内存中(随着引用计数被设置为 1),即使对象变得不可访问也是如此。

​ 举例来说,下面的接口接受对另一个同类型接口的引用,而类通过内部引用实现这一个功能:

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;

​ 如果创建两个对象并交叉引用,就会导致内存泄漏:

var
  One, Two: ISimpleInterface;
begin
  One := TObjectOne.Create;
  Two := TObjectOne.Create;
  One.AddObjectRef(Two);
  Two.AddObjectRef(One);

​ 现在,在Delphi中的解决方案是将私有字段 AnotherObj 标记为弱引用(weak interface reference):

private
  [weak] AnotherObj: ISimpleInterface;

​ 有了这一改动,在将对象作为参数传递给 AddObjectRef 调用时,引用计数不会被修改,而是保持为 1,当变量离开作用域时,引用计数会归零,从而将对象从内存中释放出来。

​ 现在有了这一功能,在许多其他类似情况下都变得非常方便,尽管底层实现非常复杂。弱引用是一项重要的功能,但要完全掌握它还需要进一步的努力。此外,由于弱引用是受管理的(而不安全引用则不受管理),因此在运行时也会产生一些代价。

​ 有关接口的弱引用及其工作原理的更多信息,请参阅第 13 章 "对象与内存 "中的 "内存管理与接口 "一节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值