2016-08-17 51 views
4

形势德尔福管理的可用内存

我从马可·坎的书学习Delphi和我已经有经验的面向对象,因为我通常使用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。通过这种方式,我释放了内存,避免了内存泄漏。

顺便说一句,我看到我也有可能重写destructor。我不太了解FreeDestroy的行为。当我不得不摆脱我不再需要的物体时,我使用Free。当我重写一个析构函数时,我可以释放该对象并进行其他操作?

总之,什么时候使用Free?我应该什么时候更喜欢Destroy?

+0

对不起阿尔伯托关于在答案评论中发生的战争。这是一场持续数十年的古代战争。但是,这是一个很好的机会让你更深入地了解手头的主题。 –

+0

不用担心,所有的东西都可以用来学习:) –

回答

7

通常,如果您需要在对象销毁期间执行某些操作,则会使用析构函数,否则这些操作不会自动完成。就像释放你在构造函数中初始化的内存一样。在你的例子中,没有必要重写析构函数,因为(大概)你不会创建任何需要手动销毁的东西。

另外,请记住,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; 

只是作为一个补充说明,我在上面看到的用法是失去了一些东西。如果CreateFree之间的代码引发一些异常,该怎么办?程序将退出,并且永远不会被释放。因此,相反,你应该使用try/finally块...

a := TFraction.Create(225, 35); 
try 
    ShowMessage(a.getFraction); 
finally 
    a.Free; 
end; 

这将确保无论tryfinally之间发生了什么,finallyend之间的代码将总是被调用。

+0

“破坏不是被称为”这是不正确的。 –

+0

@FreeConsulting你可以详细说明这个说法,并且考虑回复Ken对Remy的回答的评论吗?你能打电话吗?是。有没有理由直接调用它?不是我所知道的。或者你是否只是寻找理由来证明我所说的与其他人一样的错误? –

+1

非常感谢。我已经阅读了关于记忆管理的书的下一章,并且我找到了你告诉我的内容。我将使用Free,因为他“决定”什么时候调用析构函数。谢谢:) –

3

顺便说一句,我看到我也有可能重写destructor。我不太了解FreeDestroy的行为。

Free()如果对象指针不为零,则调用析构函数。

Destroy()是实际的析构函数。

我使用Free当我必须摆脱我不再需要的对象时。当我重写一个析构函数时,我可以释放该对象并进行其他操作?

是的。当对象处于被销毁的过程中时,调用析构函数。覆盖析构函数是执行与正在销毁的对象相关的清理操作的好地方。

总之,什么时候使用Free?我应该什么时候更喜欢Destroy?

可以呼叫Destroy()直接,但一般最好是打电话Free(),而不是让它叫Destroy()你。

+2

你能否提供一个具体的例子,你什么时候需要调用Destroy而不是Free?我无法想起曾经穿过其中的一个,并且让它成为一种永不叫摧毁自己的习惯;我很想看到我缺少的这种做法的例外。 –

+2

如果你知道*确定*给定的对象指针是* never * nil(比如用'try/finally'包装的局部变量),你可以*直接调用Destroy()。如有疑问,请改用'Free()'。在RTL/VCL源代码中,有一些直接调用Destroy()的例子(并不是很多,请注意)。例如,在'TComponent.DestroyComponents()' –

+0

@Remy也许,但是如果构造函数本身引发了一个异常开始会发生什么?我会说'Destroy'只被那些对自己的代码过于自信的人所使用,这种自信的程度实际上会变得危险。 –