Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi管理可用内存_Delphi - Fatal编程技术网

Delphi管理可用内存

Delphi管理可用内存,delphi,Delphi,形势 我在Marco Cantu的书中学习Delphi,我已经有了OOP的经验,因为我通常使用Java和PHP。为了更好地理解我正在阅读的内容,我做了以下测试: type TFraction = class private number: double; num, den: integer; fraction: string; function hcf(x: integer; y: integer): integer; public constructor

形势

我在Marco Cantu的书中学习Delphi,我已经有了OOP的经验,因为我通常使用Java和PHP。为了更好地理解我正在阅读的内容,我做了以下测试:

type
 TFraction = class
  private
   number: double;
   num, den: integer;
   fraction: string;
   function hcf(x: integer; y: integer): integer;
  public
   constructor Create(numerator: integer; denominator: integer); overload;
   constructor Create(value: string); overload;
   function getFraction: string;
 end;
这是一个非常简单的类,可以将十进制数转换为小数。我不包括我定义构造函数和函数的代码的其他部分,因为它们对我的问题没有用处。我以这种方式创建对象

var a: TFraction;
begin

 a := TFraction.Create(225, 35);
 ShowMessage(a.getFraction);
 //The output of ^ is 45/7
 a.Free;

end;

问题

从我所学到的,我知道一旦我使用了它,我就必须扔掉它,事实上我正在使用免费的
。通过这种方式,我释放了内存,避免了内存泄漏

顺便说一下,我还可以重写析构函数。我不太了解
免费
销毁
的行为。当我不得不扔掉一个我不再需要的东西时,我会使用
Free
。当我重写析构函数时,我可以释放对象并执行其他操作


简而言之,什么时候使用免费软件好?我应该在什么时候选择销毁?

一般来说,如果在对象销毁过程中需要执行某些操作,则会使用析构函数,否则将无法自动执行这些操作。就像释放在构造函数中初始化的内存一样。在您的示例中,不需要重写析构函数,因为(大概)您不创建任何需要手动销毁的内容

另外,请记住,
Destroy
根本不打算由您调用,无论是内部调用还是外部调用
Free
会自动为您处理呼叫,只需进行一点额外的工作
Free
检查对象是否为
nil
,如果不是
nil
,则只调用
Destroy

以此为例:

type
  TMyObject = class(TObject)
  private
    FSomeOtherObject: TSomeOtherObject;
  public
    constructor Create;
    destructor Destroy; override;
  end;

constructor TMyObject.Create;
begin
  inherited;
  FSomeOtherObject:= TSomeOtherObject.Create;
end;

destructor TMyObject.Destroy;
begin
  FSomeOtherObject.Free;
  inherited;
end;
作为补充说明,我在上面看到的用法缺少了一些东西。如果
Create
Free
之间的代码引发了一些异常怎么办?程序将退出,它将永远不会自由。因此,您应该使用
try/finally

a := TFraction.Create(225, 35);
try 
  ShowMessage(a.getFraction);
finally
  a.Free;
end;
这将确保无论在
try
finally
之间发生什么,都将始终调用
finally
end
之间的代码

顺便说一下,我还可以重写析构函数。我不太了解
免费
销毁
的行为

Free()
如果对象指针不是nil,则调用析构函数

Destroy()
是实际的析构函数

当我不得不扔掉一个我不再需要的东西时,我会使用
Free
。当我重写析构函数时,我可以释放对象并执行其他操作

对。当对象处于销毁过程中时,将调用析构函数。重写析构函数是执行与要销毁的对象相关的清理操作的好地方

简而言之,什么时候使用免费软件好?我应该什么时候选择毁灭


您可以直接调用
Destroy()
,但通常更倾向于调用
Free()
,让它为您调用
Destroy()

您能否提供一个具体示例,说明何时需要调用Destroy而不是Free?我记不起曾经遇到过这样的人,并且把永远不要称之为“毁灭自己”作为一种习惯;我很想看到我所缺少的这种做法的一个例外。如果您确实知道给定的对象指针永远不会为零(例如用
try/finally
包装的局部变量),您可以直接调用
Destroy()
。如有疑问,请调用
Free()
。在RTL/VCL源代码中,有一些直接调用
Destroy()。例如,在
TComponent.DestroyComponents()
Free()
中引入DestroyComponents是因为构造函数可能会出现异常,因为析构函数会自动调用。在进入构造函数之前,对象内存为零,以确保析构函数中任何未初始化的成员都为零/nil。这样,析构函数编写器就不必跟踪在异常发生之前初始化了哪些成员。我不是说不要使用
Free()
。我们大多数人(包括我自己)都这样做。我只是说当你知道这样做是安全的,并且你不需要检查
nil
,就可以直接调用
Destroy()
。Allen Bauer早在2006年就写过关于这个主题的博客:我认为这里的争论源于“可以”和“应该”之间的区别。我可以决定把伏特加倒进汽车的油箱里。但我应该吗?我认为不是,只是为了安全。“破坏不是有意被称为”这是不正确的。“自由兑换你能详细说明这个说法,也考虑回复肯对里米的回答的评论吗?”你能叫它吗?对有没有直接打电话给它的理由?我不知道。或者你只是想找个理由来证明我说的话和其他人一样不对?非常感谢。我已经阅读了这本书关于记忆管理的下一章,我已经找到了你告诉我的。因为他“决定”何时调用析构函数,所以我将使用Free。谢谢:)@FreeConsulting:除了从继承的析构函数调用之外,不能直接调用它。这是100%正确的。始终使用
Free
,不要直接调用
Destroy
,即使在某些情况下,您确定对象不是
nil
,因为这意味着您必须做出决定,而且情况可能会改变。如果你总是叫
免费
,你就不必做决定,也不会错。@Rudy True,即使这样,也只是一个简单的
继承是所有需要的