我总是尝试创建具有内存使用情况的应用程序,如果你不需要它,那么不要创建它就像我看待它一样。
无论如何,请以下面的例子为例:
Form2:= TForm2.Create(nil);
try
Form2.ShowModal;
finally
Form2.FreeOnRelease;
end;
我实际上认为Form2.Destroy可能是更好的选择,这让我想到了我的问题..
致电:
之间有什么区别?Form2.Destroy;
Form2.Free;
Form2.FreeOnRelease;
他们都做同样或类似的工作,除非我遗漏了什么。
还应该何时使用上述任何一种?显然,在释放对象时,我理解这一点,但在某些情况下,Destroy
比Free
更适合吗?
答案 0 :(得分:14)
Form2:= TForm2.Create(nil);
这是一种代码味道,因为Form2
可能是IDE生成的全局变量,通常包含IDE创建的TForm2
。您最有可能想要使用局部变量,并使用更好的名称。这不是一个错误,只是一个代码味道。
Form2.Destroy与Form2.Free
使用Form2.Free
,因为它无论如何都会调用Destroy
。你可以 CTRL + 点击名称(Free
)上的来查看它的实现。如果Free
不是零,则基本上Destroy
会调用Self
。
Form2.FreeOnRelease
正如documentation所说,"It should not be necessary to call FreeOnRelease directly."
答案 1 :(得分:9)
我以前从未真正听说过FreeOnRelease
。快速的谷歌搜索出现了原因。 From the official documentation:
当一个人调用FreeOnRelease时 由组件实现的接口 被释放。使用FreeOnRelease 在内部并调用相应的 界面方法。它不应该 调用FreeOnRelease所必需的 直接
至于Free
与Destroy
,Free
是一项安全功能。它基本上实现为if self <> nil then self.Destroy;
,它的创建是为了使构造函数和析构函数安全使用。这是基本的想法:
如果您正在构造一个对象并且引发了一个未处理的异常,则会调用析构函数。如果您的对象包含其他对象,那么在错误发生之前它们可能已经创建或者尚未创建,因此您不能只尝试在所有对象上调用Destroy
。但是你需要一种方法来确保已经创建的那些被破坏。
由于Delphi在调用构造函数之前将对象的地址空间清零,因此此时尚未创建的任何内容都保证为 nil 。所以你可以一次又一次地对所有子对象说if FSubObject <> nil then FSubObject.Destroy
(如果你忘记了你将会遇到访问冲突),或者你可以使用Free
方法,为了你。 (这是对C ++的巨大改进,在调用构造函数之前,内存空间不归零,这要求您将所有子对象包装在智能指针中并使用RAII来维护异常安全! )
它在其他地方也很有用,并且没有理由不使用它。我从来没有注意到Free
强加了任何可衡量的性能损失,并且它提高了代码的安全性,因此在所有情况下使用它都是个好主意。
话虽如此,在专门处理表单时,还有一个额外的变量来计算公式:Windows消息队列。您不知道是否还有待释放的表单的待处理消息,因此在表单上调用Free
并不总是安全的。为此,有Release
方法。它会向队列发送一条消息,导致表单在没有更多消息需要处理时自行释放,因此通常是释放不再需要的表单的最佳方式。
答案 2 :(得分:6)
规范形式是:
Form := TMyForm.Create(nil);
try
Form.ShowModal;
finally
Form.Free;
end;
永远不要致电Destroy
,而是始终致电Free
。
FreeOnRelease
是一只红鲱鱼。有时,如果有排队的邮件发往您的表单或其子级,那么您可能会选择调用Release
,尽管这通常表明存在设计问题。
答案 3 :(得分:4)
习惯用法是
procedure SomeProc;
var
frm: TForm2;
begin
frm := TForm2.Create(nil);
try
frm.ShowModal;
finally
frm.Free;
end;
end;
或者,除非你讨厌with
构造,
with TForm2.Create(nil) do
try
ShowModal;
finally
Free;
end;
根据the documentation,您永远不应该致电Destroy
。事实上,Free
完全等同于if Self <> nil then Destroy;
。也就是说,它是Destroy
的“安全”版本。如果指针恰好是nil
,它不会完全崩溃。 [要对此进行测试,请在表单类中添加私有字段FBitmap: TBitmap
,然后在OnCreate中添加(例如),尝试FBitmap.Free
与FBitmap.Destroy
。[]
如果您使用上述方法创建表单,Free
非常安全,除非您在表单类中执行一些奇怪的操作。
但是,如果使用CreateForm(TForm2, Form2)
创建表单并将表单对象存储在全局实例变量Form2
中,并且不立即释放它[例如,如果您希望窗口为你可以使用Release
代替Free
,以非模态方式在主窗体旁边停留几分钟]。来自the documentation,
发布不会破坏表单 直到表格的所有事件处理程序 和组件的事件处理程序 表格已完成执行。 发布也保证了所有 表单事件队列中的消息是 在表单发布之前处理。 表单或其表单的任何事件处理程序 孩子们应该使用Release而不是 免费(Delphi)或删除(C ++)。失败 这样做会导致内存访问 错误。
FreeOnRelease
对表单没有任何特别的处理。来自文档:
没有必要打电话 FreeOnRelease直接发布。
答案 4 :(得分:0)
另一种方式是将caFree传递给formonclose的Action
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end