在Delphi中,为什么在调用析构函数后Assigned()函数仍然返回True?
下面的示例代码将向控制台写入"sl仍然已分配".
但是,我可以打电话给FreeAndNil(sl); 它不会被分配.
我已经在Delphi中编程了一段时间,但这对我来说没有意义.
谁能解释一下?
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, Classes;
var
sl : TStringList;
begin
sl := TStringList.Create;
sl.Free;
if Assigned(sl) then
WriteLn('sl is still assigned')
else
WriteLn('sl is not assigned');
end.
Run Code Online (Sandbox Code Playgroud)
我尝试比较VCL操作... FreeAndNil简短而且很有意义:
procedure FreeAndNil(var Obj);
var
P: TObject;
begin
P := TObject(Obj);
TObject(Obj) := nil; // clear the reference before destroying the object
P.Free;
end;
Run Code Online (Sandbox Code Playgroud)
但TObject.Free是神秘的汇编程序,我不明白:
procedure TObject.Free;
asm
TEST EAX,EAX
JE @@exit
MOV ECX,[EAX]
MOV DL,1
CALL dword ptr [ECX].vmtDestroy
@@exit:
end;
Run Code Online (Sandbox Code Playgroud)
Too*_*the 37
如果使用sl.Free,则释放对象但变量sl仍指向现在无效的内存.
使用FreeAndNil(sl)释放对象并清除指针.
顺便说一下,如果你这样做:
var
sl1, sl2: TStringList;
begin
sl1 := TStringList.Create;
sl2 := sl1;
FreeAndNil(sl1);
// sl2 is still assigned and must be cleared separately (not with FreeAndNil because it points to the already freed object.)
end;
procedure TObject.Free;
asm
TEST EAX,EAX
JE @@exit // Jump to exit if pointer is nil.
MOV ECX,[EAX]
MOV DL,1
CALL dword ptr [ECX].vmtDestroy // Call cleanup code (and destructor).
@@exit:
end;
Run Code Online (Sandbox Code Playgroud)
Rod*_*ddy 14
Delphi VCL'对象'实际上总是指向对象,但这个方面通常对你隐藏.只是释放对象使指针悬空,所以你应该使用FreeAndNil.
"Mysterious Assembler"大致翻译为:
if Obj != NIL then
vmtDestroy(obj); // which is basically the destructor/deallocator.
Run Code Online (Sandbox Code Playgroud)
因为首先免费检查NIL,所以多次调用FreeAndNil是安全的......