让 C++Builder/Delphi 在启动时创建 TForms,还是手动创建?
Posted
技术标签:
【中文标题】让 C++Builder/Delphi 在启动时创建 TForms,还是手动创建?【英文标题】:let C++Builder/Delphi create TForms at launch, or create manually? 【发布时间】:2011-05-08 02:10:15 【问题描述】:在 Builder(或 Delphi)中创建 TForm 时,将代码添加到 main
以在应用程序启动时创建这些表单:
Application->CreateForm( __classid( TxForm), &xForm );
这使事情变得更容易,但是当应用程序有 10、20、50、100 个表单时是否明智?我假设这可以获取各种内存和系统句柄。需要时,可以随时使用 Project->Options->Forms 对话框删除表单,并随时创建表单:
std::auto_ptr< TxForm > myForm( new TxForm( this ));
myForm->ShowModal();
那么问题来了,是让 C++ Builder 自己做,还是在需要时手动创建表单更好?
【问题讨论】:
当然,您可以通过从项目>>选项>>表单的自动创建表单列表中删除它们来使Delphi不自动创建有问题的表单。你可能已经知道了,但我认为应该在问题中提及它。 正确,为了清楚起见,我会将其添加到问题中。 【参考方案1】:除非应用程序只是一个非常小的测试台或 POC, 只创建主表单(和/或全局数据模块,如果它是 您的风格/设计)并手动创建所有其他人。
在加载时创建所有表单只是一种浪费,并且(取决于 在表单上做了什么)可以让你的程序加载得像大海一样快 乌龟在沙滩上行走……
【讨论】:
【参考方案2】:建议让 IDE“按照自己的方式做”意味着 IDE 正在使用某种智能来生成用于创建表单和数据模块的代码。 不是。它只是按照你告诉它使用的顺序创建你告诉它创建的东西。如果您没有通过项目选项对话框明确告诉它要做什么,那么它只是按照您将它们添加到项目中的顺序创建事物。 IDE 并不比你更了解。
使用自动创建的表单和数据模块鼓励使用 IDE 为您声明的全局变量来引用这些对象。你不需要它们。
仅自动创建您的主表单。当您需要其他任何东西时,请使用创建对象的典型方式自己创建它:调用构造函数,并将对对象的引用存储在其他对象的局部变量或字段中,而不是 IDE 提供的全局变量中,您应该删除它们。不要打扰CreateForm
。 I wrote an article explaining why.
【讨论】:
无意暗示 IDE 正在使用任何类型的智能 :-)【参考方案3】:IMO,自动创建您可能不会使用的表单,例如关于框,只是浪费。我通常会自动创建主表单,然后根据需要动态创建其余表单。
【讨论】:
【参考方案4】:这实际上取决于您如何在应用程序中使用表单。我通常在需要时即时创建它们,然后在完成后释放它们。这是更多的手动工作,但可以节省资源(每次都会花费一点 CPU,这可能会导致延迟)。
如果您很少使用表单,我会说在需要时手动创建/释放(删除),但如果您一直使用表单并且在应用程序的整个生命周期中使用,请使用默认方式。
【讨论】:
【参考方案5】:已创建但尚不可见的表单会占用内存并影响启动时间,但不应使用任何系统句柄,因为在窗口实际显示之前不会分配窗口句柄等内容。
话虽如此,我几乎总是手动创建表单(使用类似于您的auto_ptr
的代码),因为我无法忍受全局变量。手动创建表单有几个优点:更快的应用程序启动,表单总是以已知的良好状态显示,并且如果需要,以后更容易切换到一次显示多个表单实例。
作为the VCL documentation explains,delete
直接(或间接,通过使用股票std::auto_ptr
)可能会导致内存错误,因为该表单可能有未处理的消息。为了避免这个问题,我编写了两个智能指针类来处理调用Release
而不是delete
。你可以从http://gist.github.com/671452下载。
【讨论】:
为什么你的 DeleteOrRelease() 调用 delete。根据文档发布每次都会完成这项工作? 如果你看Release的源代码,它调用PostMessage(Handle, ...)
,读取Handle属性的值调用HandleNeeded,它分配一个句柄(即分配一堆Windows资源需要在屏幕上显示表格)。在我看来,对于一个从未显示或窗口句柄已被销毁的窗体来说,分配一个句柄只是为了让您可以立即释放它,这似乎很愚蠢。如果 !HandleAllocated 调用 delete 是一个微优化,但它从来没有给我带来任何问题。
如果您仔细阅读 VCL 文档,它会说:“表单或其子项的任何事件处理程序都应该使用 Release 而不是 Free (Delphi) 或 delete (C++ ). 不这样做会导致内存访问错误。”表单的事件处理程序需要使用 Release() 而不是 Free() 或 delete,但任何其他不在表单事件处理程序上下文中调用的代码都可以安全地使用 Free() 或 delete不用担心“内存错误”。
上面链接的同一个文档也有这样的明确行:使用Release来销毁表单并释放其相关的内存。所以,我们仍然必须使用Release,但不是因为可能的内存错误?
@Remy:感谢您的澄清。实际上,我的事件处理程序链最终以从其自己的事件处理程序中释放的形式结束,因此我可能会继续在我自己的代码中使用 Release。以上是关于让 C++Builder/Delphi 在启动时创建 TForms,还是手动创建?的主要内容,如果未能解决你的问题,请参考以下文章
linux shell脚本执行命令时创建子进程问题(特定的情况,例如后台运行管道分支或子shell等,脚本可能会创建子进程执行命令)
linux shell脚本执行命令时创建子进程问题(特定的情况,例如后台运行管道分支或子shell等,脚本可能会创建子进程执行命令)