首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对象的引用计数

对象的引用计数
EN

Stack Overflow用户
提问于 2009-04-23 10:10:09
回答 7查看 6.6K关注 0票数 8

在我的代码中,我使用了一个在不同地方创建的小型数据存储类。为了避免内存泄漏和简化,我想使用引用计数,所以我做到了。

代码语言:javascript
复制
type TFileInfo = class (TInterfacedObject, IInterface)

并删除了我对TFileInfo.Free的所有手动调用。不幸的是,Delphi报告了大量内存泄漏。通过搜索,我发现了以下问题,解释了为什么这不起作用:

为什么没有收集TInterfacedObject垃圾的后代?

这里有一个解决方案,但它要求我(至少如果我做对了)编写一个自定义接口IFileInfo,并为它提供大量的getter和setter,这是我想要避免的。

编辑--我应该将create FileInfo对象插入到两种不同类型的哈希表中:一种是从TBucketList降序的哈希表,另一种是来自Codegear论坛的哈希映射实现。在内部,它们都是用户指针,所以情况就像在另一个问题中一样。

在Delphi中是否还有其他可能使用引用计数来生成对象?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-04-23 10:42:10

不幸的是,Delphi编译器只在使用接口(在您的例子中是自定义接口IFileInfo)时才生成必要的代码到inc/dec引用计数。此外,如果接口被转换为指针(或TObject ),则同样不可能进行引用计数。例如,假设全局变量列表: TList:

代码语言:javascript
复制
var ifi : IFileInfo;
begin
  ifi := TFileInfo.Create;
  list.Add(TFileInfo(ifi));
end;

方法返回后,listlist.Count -1将包含悬空指针。

因此,不能在将接口转换为指针的hashmap中使用接口,因此hashmap实现必须将它们保持为IInterface。

票数 6
EN

Stack Overflow用户

发布于 2009-04-23 17:03:51

只有当您只有通过接口引用实例时,Delphi中的引用计数才能工作。一旦将接口引用和类引用混合在一起,就会遇到麻烦。

本质上,您需要引用计数,而不需要创建包含其中定义的所有方法和属性的接口。有三种方法可以做到这一点,这些方法大致按我推荐的顺序排列。

  1. 巴里·凯利写了一篇关于智能指针的文章。它使用Delphi 2009中的Generics,但我非常肯定,如果您还没有使用2009年(它是一个很好的版本BTW),您可以将它硬编码到您正在使用的特定版本中。
  2. 另一种使用更多版本的Delphi和更少修改的方法是Janez Atmapuri Makovsek的值类型包装器。它是为TStringList实现的一个示例,但您可以将它修改为任何类型。
  3. 第三种方法是创建一个接口指针(类似于Barry的智能指针,但不太智能)。我相信JCL里有一个,但我不太清楚细节。基本上,这是一个在构造时接受TObject引用的接口。然后,当它的引用计数达到零时,它对传递给它的对象调用空闲。此方法实际上只适用于不作为参数传递的短暂实例,因为您将引用计数引用与实际使用的引用分开。我会推荐另外两种方法中的一种,但是如果您喜欢这种方法并且想要更多的信息,请告诉我。

这就是德尔菲的问题,有一种免费的方法来完成一些事情。选项1是最好的,在我看来-得到德尔菲2009,并使用该方法,如果你可以的话。

祝好运!

票数 8
EN

Stack Overflow用户

发布于 2009-04-23 14:37:16

不要混合对象引用和接口引用。

代码语言:javascript
复制
var
  Intf: IInterface;
  Obj: TFileInfo;

begin
  // Interface Reference
  Intf := TFileInfo.Create; // Intf is freed by reference counting, 
                            // because it's an interface reference
  // Object Reference
  Obj := TFileInfo.Create;
  Obj.Free; // Free is necessary

  // Dangerous: Mixing
  Obj := TFileInfo.Create;
  Intf := Obj; // Intf takes over ownership and destroys Obj when nil!
  Intf := nil; // reference is destroyed here, and Obj now points to garbage
  Obj.Free; // this will crash (AV) as Obj is not nil, but the underlying object
            // is already destroyed
end;
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/781100

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档