2016-08-17 120 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'只被那些對自己的代碼過於自信的人所使用,這種自信的程度實際上會變得危險。 –