我是否可以在不釋放它們的情況下繞過class
es,或者我的軟件是否會開始泄漏泄漏?Object Pascal:是否必須釋放所有對象(類)?
例如,我可以做到這一點
Engine := TEngine.Create(TV);
然後得到沒有任何問題擺脫參考的,或者我必須先調用其Free
方法?
或者有一個函數返回一個TSomething
而不必稍後釋放它的引用?
我是否可以在不釋放它們的情況下繞過class
es,或者我的軟件是否會開始泄漏泄漏?Object Pascal:是否必須釋放所有對象(類)?
例如,我可以做到這一點
Engine := TEngine.Create(TV);
然後得到沒有任何問題擺脫參考的,或者我必須先調用其Free
方法?
或者有一個函數返回一個TSomething
而不必稍後釋放它的引用?
一般規則是,如果你創建它,你應該釋放它。最好的辦法是在try..finally,如果你在代碼中創建它:
var
Engine: TEngine;
begin
Engine := TEngine.Create(TV);
try
// Do stuff with Engine
finally
Engine.Free;
end;
end;
的例外是,如果你有一個接受業主作爲一個參數(一個對象,如可視化控件像TEdit
或TComponent
的非目視後裔)。如果您分配所有者,則在所有者被釋放時它將釋放它。 (如果您沒有所有者創建它,你還是要自己解放出來。)
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;
從技術上講,你用構造函數初始化的所有內容都必須明確地釋放。
但也有一些簡單的解決辦法,妥善使用時,最能節省你的麻煩:
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的實現將自動調用該析構函數。
不能強調TComponent所有者機制純粹是一個庫慣例。在語言層面上,它仍然必須被釋放,只是FCL/VCL爲你做了一些管理。 –
@KenWhite你還必須免費提出'例外'嗎? –
@SuperDisk:號碼:-)你不會創造它們,你*提高他們。異常處理機制將爲您處理。 –