我是Delphi的新手并且已经手动完成了所有的内存管理,但是听说Delphi能够使用接口来进行引用计数并以这种方式提供一些内存管理.我想开始这个,但有一些问题.
一般来说,我该如何使用它.创建接口和实现它的类.然后,只要我需要该对象,变量实际上是接口类型,但实例化对象和presto?没有必要考虑解放它吗?没有更多的尝试 - 终极?
为真正不需要它们的类创建一堆接口似乎非常麻烦.有关自动生成这些的提示吗?我该如何最好地组织它?接口和类在同一个文件中?
有什么常见的陷阱可能会让我感到悲伤?例如:将接口对象转换为其类的对象是否会破坏我的引用计数?或者Delphi是否有任何非显而易见的方法来创建引用循环?(除了A使用B使用C使用A)
如果有教程覆盖任何一个,那将是很好的,但我没有在我的搜索中提出任何东西.谢谢.
我目前正在处理一个非常大的项目,该项目利用接口引用计数的"副作用"来进行内存管理.
我个人的结论是,你最终得到了许多过于复杂的代码,没有更好的理由,"我不必担心自由呼叫"
出于一些非常基本的原因,我强烈建议不要采取这种行动:
1)您正在使用为了COM兼容性而存在的副作用.
2)您正在使对象占用空间和效率更高.接口是指针列表的指针..或者沿着这些行的东西.
3)就像你说的那样......你现在必须制作成堆的接口,其唯一目的就是避免自己释放记忆......这会导致比我认为更值得的麻烦.
4)在对象被引用之前,当对象被释放时,最常见的错误将是调试的巨大痛苦.我们在自己的引用中有特殊代码,在软件出门之前尝试测试这个问题.
现在回答你的问题.
1)给定TFoo和接口IFoo,您可以使用如下方法
function GetFoo: IFoo;
begin
Result := (TFoo.Create as IFoo);
end;
Run Code Online (Sandbox Code Playgroud)
...而且,你不需要最终释放它.
2)是的,就像我说的,你认为这是一个好主意,但它变成了bupkis的巨大痛苦
3)2个问题.
A)你有Object1.Interface2和Object2.Interface1 ......由于循环引用,这些对象永远不会被释放
B)在释放所有引用之前释放对象,我不能强调这些错误是多么难以追踪......
导致Delphi中"自动垃圾收集"的最常见抱怨是,即使是短暂的临时对象也必须手动处理,并且必须编写相当数量的"锅炉板"代码以确保这种情况发生在异常发生时.
例如,为过程中的某些临时排序或其他算法目的创建TStringList:
procedure SomeStringsOperation(const aStrings: TStrings);
var
list: TStringList;
begin
list := TStringList.Create;
try
:
// do some work with "list"
:
finally
list.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
正如您所提到的,实现COM引用协议的对象计算了生命周期管理,通过在释放所有对它们的引用时清除它们来避免这种情况.
但由于TStringList不是COM对象,因此您无法享受此提供的便利.
幸运的是,有一种方法可以使用COM引用计数来处理这些事情,而无需创建您希望使用的类的所有新的COM版本.您甚至不需要切换到完全基于COM的模型.
我创建了一个非常简单的实用程序类,允许我在一个轻量级的COM容器中"包装"任何对象,专门用于实现这种自动清理的目的.使用此技术,您可以将以上示例替换为:
procedure SomeStringsOperation(const aStrings: TStrings);
var
list: TStringList;
begin
AutoFree(@list);
list := TStringList.Create;
:
// do some work with "list"
:
end;
Run Code Online (Sandbox Code Playgroud)
所述AutoFree()函数调用创建一个"匿名"接口对象,该对象是推出()在由编译器的过程生成的退出代码"d.这个autofree对象传递一个指向引用你想要被释放的对象的变量的指针.除此之外,这允许我们使用AutoFree()函数作为伪"声明",将any和所有AutoFree()调用放在方法的顶部,尽可能接近它们引用的变量声明,然后我们甚至创造了任何物体.
实施的全部细节,包括源代码和进一步的例子,是在我的博客中的这篇文章.
| 归档时间: |
|
| 查看次数: |
1318 次 |
| 最近记录: |