我对OO Delphi的最佳实践有一个普遍的疑问.目前,我将try-finally块放在我创建对象的任何地方,以便在使用后释放该对象(以避免内存泄漏).例如.:
aObject := TObject.Create; try aOBject.AProcedure(); ... finally aObject.Free; end;
代替:
aObject := TObject.Create; aObject.AProcedure(); .. aObject.Free;
你认为这是好的做法还是过多的开销?那表现怎么样?
解决方法
在我看来,只有一个原因是对象构造不应该遵循(
or “in” as Mason pointed out)try / finally块.
>如果对象的生命周期由另一个对象管理.
这种管理可以采取三种形式:
>对象的引用具有超出本地块的范围,并在其他地方释放 – 就像在析构函数中释放的字段成员一样.
>一个对象立即添加到一个列表中,该列表稍后负责释放该对象.
>具有关联生命周期管理器的对象,就像在构造时将所有者传递给VCL控件一样.
对于#1,当引用具有更宽的范围时,如果不立即构造引用,则应立即将引用设置为nil.这样,当检查参考时,您知道您有准确的读数.这对于构造为较大类的一部分的成员对象最常见,然后在销毁父对象时进行清理.
对于#2,当一个对象被添加到列表中时,你想要使用一个try-except块(我用过的几次之一),以防万一在构造对象之后和添加到对象之前发生异常.管理清单.理想情况下,构造后的第一行是将其添加到列表中,或者列表实际上是一个工厂类,它为您提供已添加到列表中的对象.
对于#3,当一个对象有另一个生命周期管理器时,你真的应该确保由该管理器管理它是正确的事情.如果你正在构建一个VCL控件,你可能会想让表单(或任何其他控件)拥有它,但这实际上会给构造和破坏带来额外的开销.如果可能的话,你应该明确地释放它,如果你把控件放在一次,那么你知道你将在你的表单的析构函数中或者它关闭时释放它,尤其如此.唯一不能做到这一点的是控件创建是否更具动态性.
所以是的,使用大量的try / finally块是最好的做法.您应该只有几个try / except块,并且大多数都应该捕获非常特定的异常类型,和/或重新引发异常.如果你有更多尝试/除了try / finally块,那么你做错了.