jpf*_*ius 8 delphi interface reference-counting tinterfacedobject
在我的代码中,我使用了一个小型数据存储类,它在不同的地方创建.为了避免内存泄漏并简化操作,我想使用引用计数,所以我做到了
type TFileInfo = class (TInterfacedObject, IInterface)
Run Code Online (Sandbox Code Playgroud)
并删除了我对TFileInfo.Free的所有手动调用.不幸的是Delphi报告了很多内存泄漏.搜索SO我发现以下问题解释了为什么这不起作用:
这里有一个解决方法,但它需要我(至少如果我做对了)编写一个自定义接口IFileInfo并为它提供了许多getter和setter,我想避免它.
编辑我应该补充一点,我将创建的FileInfo对象插入到两种不同类型的哈希表中:一个来自TBucketList,另一个是来自Codegear论坛的哈希映射实现.在内部它们都是用户指针,因此情况就像在另一个问题中一样.
还有其他可能使Delphi中的对象使用引用计数吗?
Delphi中的引用计数仅在您通过接口仅引用实例时才有效.只要混合接口引用和类引用,就会遇到麻烦.
基本上,您需要引用计数,而无需使用其中定义的所有方法和属性创建接口.有三种方法可以做到这一点,这些方法大致按我推荐的顺序排列.
Barry Kelly写了一篇关于Smart Pointers的文章.它使用Delphi 2009中的Generics,但我很确定你可以硬编码到你正在使用的特定版本的类型,如果你还没有使用2009(它是一个伟大的发布BTW).
使用更多版本的Delphi和更少修改的另一种方法是Janez Atmapuri Makovsek 的值类型包装器.这是为TStringList实现的示例,但您可以针对任何类型进行调整.
第三种方法是创建一个接口指针(类似于Barry的智能指针,但不是那么聪明).我相信JCL中有一个,但我不记得确切的细节.基本上这是一个在构造时接受TObject引用的接口.然后,当它的引用计数达到零时,它会在您传递给它的对象上调用free.此方法实际上仅适用于未作为参数传递的短期实例,因为您将引用计数引用与实际使用的引用分开.我建议使用其他两种方法中的一种,但如果您更喜欢这种方法并想了解更多信息,请告诉我.
这就是德尔福的事情,有一种自由的方式来完成事情.在我看来,选项#1是最好的 - 如果可以的话,获取Delphi 2009并使用该方法.
祝好运!
遗憾的是,只有在使用接口(在您的情况下是自定义接口IFileInfo)时,Delphi编译器才会为inc/dec引用计数生成必要的代码.此外,如果接口被强制转换为指针(或者TObject),那么也不能进行引用计数.例如,假设全局变量列表:TList:
var ifi : IFileInfo;
begin
ifi := TFileInfo.Create;
list.Add(TFileInfo(ifi));
end;
Run Code Online (Sandbox Code Playgroud)
方法返回后,list [list.Count - 1]将包含悬空指针.
因此,接口不能用于将它们转换为指针的hashmap,hashmap实现必须将它们保留为IInterface.
| 归档时间: |
|
| 查看次数: |
5530 次 |
| 最近记录: |