三、解決問題
在解決問題之前,我們先進行如下的規定:
TAutoPtr<T>中的T智能傳入Class類型或指針類型,不能傳入如Integer、record這樣的保存在棧上的類型,因為這樣是沒有意義的。如果能有這樣的約束:“TAutoPtr<T: class or Pointer>”就好了
解決問題:
1、“fObj := nil”,fObj為指針,我們可以改成“Integer((@fObj)^) := 0;”
2、“aObj <> fObj”,有了第一點,第二點也好改了:“Integer((@aObj)^) <> Integer((@fObj)^)”
3、“if fObj = nil then” ,改為:“if Integer((@fObj)^) <> 0 then”
4、這一點比較麻煩,因為我們即使按照約定T必須為class或Pointer,fObj必須為一個指針,也不能擁有像c++一樣的delete函數。 雖然Delphi擁有Dispose函數,但是Dispose函數不能夠實現Free方法。
所以,我們必須根據T的類型分別處理,如果是class型則Free,如果是指針類型則用另外一種方法處理。
首先,我們通過如下方法獲取T的類型信息:
uses
TypInfo;
var
fTypeInfo:PTypeInfo;
begin
//獲取泛型的類型
fTypeInfo:=TypeInfo(T);
end;
1)針對於class類型,我們可以這樣處理:
if fTypeInfo.Kind = tkClass then
TObject((@fObj)^).Free;
2)由於Pointer不包含類型信息,如果T為Pointer,則fTypeInfo為nil。然而,釋放指針有兩種方法,Dispose和FreeMem。關於Dispose和Freemem的區別,請閱讀以下文章《Delphi的指針》。
通過查看System.pas中的代碼我發現,Delphi在Dispose的時候已經調用了FreeMem方法:
PUSH EAX
CALL _Finalize
POP EAX
CALL _FreeMem