北京做网站推广的公司,商城网站的设计风格,家里电脑可以做网站服务器吗,房屋设计图制作软件13.4 内存管理和接口
在第11章中#xff0c;我介绍了接口的内存管理的关键要素。与对象不同#xff0c;接口是受管理且具有引用计数。如我所提到的#xff0c;接口引用会增加所引用对象的引用计数#xff0c;但您可以声明接口引用为弱引用以禁用引用计数#xff08;但…13.4 内存管理和接口
在第11章中我介绍了接口的内存管理的关键要素。与对象不同接口是受管理且具有引用计数。如我所提到的接口引用会增加所引用对象的引用计数但您可以声明接口引用为弱引用以禁用引用计数但仍然要求编译器为你管理引用或者您可以使用unsafe修饰符完全禁用对特定引用的任何编译器支持。在这一节中我们将深入探讨这个领域展示一些在第11章中提供示例之外的额外示例。
13.4.1 关于弱引用的更多内容
Delphi 对接口使用的引用计数模型存在一个问题即如果两个对象相互引用它们将形成循环引用并且它们的引用计数基本上永远不会降至零。弱引用提供了一种打破这些循环的机制允许您定义一个不会增加引用计数的引用。
假设两个接口使用它们的字段相互引用而外部变量引用第一个接口。第一个对象的引用计数将为2外部变量和第二个对象的字段而第二个对象的引用计数为1第一个对象的字段。图13.4描述了这种情况。
图 13.4 对象间的引用 对象之间的引用可以形成循环、 弱引用的原因
现在当外部变量退出作用域时两个对象的引用计数为1并且由于拥有Object2的主对象Object1没有外部所有者因此这两个对象将无限期保留在内存中。为解决这种情况您应该打破循环引用这是一件相当复杂的事情因为您不知道何时执行此操作应在最后一个外部引用超出范围时执行但这是对象无法知道的事实。
解决这种情况以及许多类似情况的方法是使用弱引用。如前所述弱引用是对对象的引用不会增加其引用计数。从技术上讲您通过对其应用[weak]attribute来定义弱引用。 注解 Attributes是第16章将介绍的Object Pascal高级语言功能。简而言之它们是一种关于符号的添加一些运行时信息的方法以便外部代码可以确定如何处理它。 再考虑一下先前的场景如果从第二个对象对第一个对象的引用是弱引用见图13.5那么当外部变量超出作用域时两个对象都将被销毁。 让我们用代码来看看这种简单情况。首先ArcExperiments 应用程序示例声明了两个接口一个引用另一个
typeIMySimpleInterface interface[{B6AB548A-55A1-4D0F-A2C5-726733C33708}]procedure DoSomething(BRaise: Boolean False);function RefCount: Integer;end;IMyComplexInterface interface[{5E8F7B29-3270-44FC-B0FC-A69498DA4C20}]function GetSimple: IMySimpleInterface;function RefCount: Integer;end; 程序的代码定义了两个实现这些接口的不同类。注意交叉引用FOwnedBy和FSimple基于接口其中一个被定义为弱引用
typeTMySimpleClass class(TInterfacedObject, IMySimpleInterface)private[Weak] FOwnedBy: IMyComplexInterface;publicconstructor Create(Owner: IMyComplexInterface);destructor Destroy; override;procedure DoSomething(BRaise: Boolean False);function RefCount: Integer;end;TMyComplexClass class(TInterfacedObject, IMyComplexInterface)privateFSimple: IMySimpleInterface;publicconstructor Create;destructor Destroy; override;function GetSimple: IMySimpleInterface;function RefCount: Integer;end; 这个“complex”类的构造函数创建了另一个类的对象
constructor TMyComplexClass.Create;
begininherited Create;FSimple : TMySimpleClass.Create(Self);
end; 请记住FOwnedBy字段是一个弱引用因此它不会增加其引用对象的引用计数在本例中它不会增加 TMyComplexClass 的引用计数。在本例中是当前对象Self。鉴于此代码结构我们可以编写
class procedure TMyComplexClass.CreateOnly;
varMyComplex: IMyComplexInterface;
beginMyComplex : TMyComplexClass.Create;MyComplex.FSimple.DoSomething;
end; 只要使用弱引用这将不会导致内存泄漏。例如使用以下代码
varMyComplex: IMyComplexInterface;
beginMyComplex : TMyComplexClass.Create;Log(Complex MyComplex.RefCount.ToString);MyComplex.GetSimple.DoSomething(False); 鉴于每个构造函数和析构函数都记录了其执行您将得到一个类似于以下的日志
kotlinCopy codeComplex class created
Simple class created
Complex 1
Simple class doing something
Complex class destroyed
Simple class destroyed 如果在代码中删除weak属性你会看到一个内存泄漏并且在上面的代码执行中引用计数为2而不是1。