在我的来源中,我经常看到并使用如下构造:
with TSQLDataSet.Create(nil) do try
//Dosomething, get a result from a query.
finally
Free;
end;
但我也经常看到结构:
with TSQLDataSet.Create(nil) do begin
//Dosomething, get a result from a query.
end;
如果我创建带有contruction的对象,我是否需要释放它们,或者在with-block结束时是自动的?
答案 0 :(得分:8)
您需要手动释放对象。 not 是真的,它们会在with
块的末尾自动释放。这通常适用 。如果TSQLDataSet
有特别之处,我不知道。
答案 1 :(得分:8)
您需要free
。
因为Class.Create
只是一个表达式,Delphi无法知道结果值来自哪个表达式。
您可以阅读VCL来源 - 始终显式.Free
。
你可以想到非对象的例子:
var r: record .... end;
with r do begin
...
end;
如果Delphi试图在with
结束时释放所有内容 - 那么它会尝试free
非对象?
with SomeObjectFactory.GetMeAnObject do begin
...
end;
这里你不是通过构造函数创建对象,而是通过某个函数创建对象。此功能与TLabel.Font
或TDataSet.FieldByName
没有区别。
Delphi free
应该在这里吗?
为了避免冒险的猜测并保持统一 - with
只是with
。这只是一个别名。而已。它的设计早在1974年,并没有克隆最新.Net / Scala Using(x){..}
结构的功能。
你可能看到的是像
这样的结构with TForm.Create(Application) do ...;
with TLabel.Create(MainForm.Panel1) do ...;
这是非常不同的 - 它确实将新创建的控件插入属于所有者。所有者free
自身free
时拥有所有自有组件。但这不会使用Create(nil)
。当它仍然存在时 - 然后在with
块内部,您将看到一些显式调用,将对象绑定到某个容器/父级(尽管在.Create
和绑定之间的异常情况下这非常脆弱)。
答案 2 :(得分:0)
Delphi(Object pascal),C,C ++以及许多非托管代码的第三代语言都有责任将内存循环给程序员。因此,在任何一种情况下,您都必须确保在代码中的任何位置释放已获取的内存。
您提供的第一个示例假定您创建的对象在结束语句后不需要处于活动状态。第二个示例假定创建对象并将其传递给End语句之后要使用的其他对象。所以using对象应该处理内存的重新分配。
在Java VM或.Net应用程序等托管代码环境中,内存由环境处理。环境会感知何时没有对已分配的内存块的引用,并在适合环境时释放它。