【问题标题】:If I create an object in a "with" clause, do I still need to free it?如果我在“with”子句中创建一个对象,我还需要释放它吗?
【发布时间】:2012-09-20 11:41:20
【问题描述】:

在我的源代码中,我经常看到并使用这样的结构:

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 构造创建对象,我需要释放它们还是在 with 块的末尾自动释放它们?

【问题讨论】:

  • 我严重怀疑您是否“经常”看到后一个版本。
  • @Andreas - 好点。但这是可能的,如果使用 body 将对象连接到某个容器。或使用非零构造函数参数
  • 如果你拥有它,你必须释放它,或者将所有权传给你。

标签: delphi delphi-7 pascal with-statement


【解决方案1】:

你需要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 ...;

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

【讨论】:

  • 我已经稍微拓宽了编程语言的视野,并阅读了有关“使用”结构的信息。然后你在你自己的代码库中找到“with someobject.create”结构,但没有明确的免费,所以我想,这是否正确。经过进一步的测试,您确实需要使用 with 语句显式释放您创建的对象。如果你不这样做,它会一直占用你的记忆。但它们不会被报告为内存泄漏。
  • 是的,Pascal 的蹩脚 with 不能与 Python 的 with 混淆
  • @David 我不会称它为“la脚”。有限的,是的。但并非所有有限的功能都是蹩脚的。
  • @Arioch'The 与其说是有限,不如说是它的力量太大了
  • @David 真的吗?我想知道...那你是什么意思在不有效移除它的情况下降低功率?
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 它比托管代码更复杂。如果有代表系统资源的对象,那么它们的生命周期不能留给 GC。例如具有句柄的文件对象。因此.net IDisposable 等等。数据库连接也是如此。
    猜你喜欢
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2011-08-16
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多