1

在我的资料中,我经常看到并使用这样的结构:

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;

如果我创建带有结构的对象,我需要释放它们还是在 with 块的末尾自动释放它们?

4

3 回答 3

8

您需要手动释放对象。在块的末尾自动释放它们是with正确的。这适用于一般情况。如果有什么特别之处TSQLDataSet,我不知道。

于 2012-09-28T15:02:48.847 回答
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并且这个函数与or没有什么不同TDataSet.FieldByName。Delphi 是否应该free在这里?

为了避免冒险的猜测并保持一致 -with是公正的with。它只是一个别名。而已。它是在 1974 年设计的,并没有克隆最新的 .Net/ScalaUsing(x){..}结构的功能。


可能看到的是这样的结构

with TForm.Create(Application) do ...;
with TLabel.Create(MainForm.Panel1) do ...;

这是非常不同的 - 它确实将新创建的控件插入为属于所有者。当它是d 本身时,所有者将free拥有它所有的组件。free但这不使用Create(nil). 当它仍然存在时 - 然后在with块内你会看到一些显式调用,将对象绑定到某个容器/父级(尽管在.Create和绑定之间发生异常的情况下这是非常脆弱的)。

于 2012-09-28T15:04:44.843 回答
0

Delphi(Object pascal)、C、C++ 和更多非托管代码的第三代语言将内存回收的责任交给了程序员。因此,无论哪种情况,您都必须确保在代码中的任何位置释放获得的内存。

您给出的第一个示例假定您创建的对象在 end 语句之后不需要处于活动状态。第二个示例假定对象已创建并传递给 End 语句后要使用的其他对象。所以使用对象应该处理内存的释放。

在 Java VM 或 .Net 应用程序等托管代码环境中,内存由环境处理。当没有对分配的内存块的引用时,环境会感知并在它适合环境时释放它。

于 2012-09-29T06:03:57.903 回答