2013-04-13 34 views
0

我是否可以在不釋放它們的情況下繞過class es,或者我的軟件是否會開始泄漏泄漏?Object Pascal:是否必須釋放所有對象(類)?

例如,我可以做到這一點

Engine := TEngine.Create(TV); 

然後得到沒有任何問題擺脫參考的,或者我必須先調用其Free方法?

或者有一個函數返回一個TSomething而不必稍後釋放它的引用?

回答

2

一般規則是,如果你創建它,你應該釋放它。最好的辦法是在try..finally,如果你在代碼中創建它:

var 
    Engine: TEngine; 
begin 
    Engine := TEngine.Create(TV); 
    try 
    // Do stuff with Engine 
    finally 
    Engine.Free; 
    end; 
end; 

的例外是,如果你有一個接受業主作爲一個參數(一個對象,如可視化控件像TEditTComponent的非目視後裔)。如果您分配所有者,則在所有者被釋放時它將釋放它。 (如果您沒有所有者創建它,你還是要自己解放出來。)

procedure TForm1.FormCreate(Sender: TObject); 
var 
    EditA, EditB: TEdit; 
begin 
    EditA := TEdit.Create(Self); // You're passing the form as owner; don't free 
    EditB := TEdit.Create(nil); // Creating without an owner; you free. 
end; 

如果類是另一個對象的成員(場),您在包含創建對象constructor和自由它它的destructor

type 
    TOuterClass = class(TObject) 
    private 
    FEngine: TEngine; 
    public 
    constructor Create; 
    destructor Destroy; override; 
    end; 

implementation 

constructor TOuterClass.Create; 
begin 
    inherited; 
    FEngine := TEngine.Create(TV); 
end; 

destructor TOuterClass.Destroy; 
begin 
    FEngine.Free; 
    inherited; 
end; 
+0

不能強調TComponent所有者機制純粹是一個庫慣例。在語言層面上,它仍然必須被釋放,只是FCL/VCL爲你做了一些管理。 –

+0

@KenWhite你還必須免費提出'例外'嗎? –

+0

@SuperDisk:號碼:-)你不會創造它們,你*提高他們。異常處理機制將爲您處理。 –

1

從技術上講,你用構造函數初始化的所有內容都必須明確地釋放。

但也有一些簡單的解決辦法,妥善使用時,最能節省你的麻煩:

1:使用TInterfacedObject:

IMyStuff = interface(IUnknown) 
    ['{9DF82155-2475-4403-8933-969DC4912AD7}'] 
    function Print:boolean; 
    procedure DoStuff; 
    end; 

    TMyStuff = class(TInterfacedObject, IMyStuff) 
    private 
     function Print:boolean; 
     procedure DoStuff; 
    end; 

實施TMyStuff就像任何其他類。但是當你用這個類在你的代碼,使用類型IMyStuff的變量,就像這樣:

procedure MyIProcedure; 
var myStuff: IMyStuff; 
begin 

    myStuff:=TMyStuff.create; 
    myStuff.DoStuff; 

end; 

沒有必要在「TMyStuff.create」呼叫投(在這種情況下 - 有時它是... ) - 因爲變量是IMystuff類型,所以這是隱含的。不需要釋放IMyStuff(實際上你不能,雖然你可以調用IMyStuff:= nil。)由於它被聲明爲一個接口類型,自動垃圾收集是使用COM引用計數模型實現的 - Delphi爲你處理當你從TInterfacedObject繼承時。

但是不會混合類類型變量:即TMyStuff與IMyStuff變量類型。這可能會導致一些令人討厭的混亂和錯誤,這會讓你撓頭。這就是我通常將TInterfacedObject的成員聲明爲PRIVATE的原因,正如我在此處所做的,通過引用TMyStuff使其無法訪問。但是他們可以通過引用IMyStuff來訪問:根據定義,所有接口成員都是公共的。除了Ken的優秀答案之外,VCL的TObjectList和TObjectDictionary爲它們包含的所有對象引用提供了自動垃圾收集(詳見Delphi文檔) - 但是它們本身必須被釋放,然後剩下的它們被釋放。

在TInterfacedObject中使用TObjectList或TObjectDictionary,並且再也不用擔心垃圾回收,只要在TInterfacedObject的析構函數中釋放ObjectList或ObjectDictionary即可。當referenceCount = 0時,Delph的實現將自動調用該析構函數。

相關問題