Free & FreeAndNil的使用。(100分)

  • 主题发起人 主题发起人 javesun
  • 开始时间 开始时间
J

javesun

Unregistered / Unconfirmed
GUEST, unregistred user!
只知道他们两者的区别,可在什么地方使用却不知道。。。

哪位大虾给个例子看看?
 
常用用法是,一个Tobject变量 obj
如果需要判断obj=nil 时,则在释放obj时最好调用FreeAndNil(),这样确保obj被赋值为nil
如果只用free,则无法正确判断出 obj是否等于nil 因为此时的obj仍指向原先有效free后无效的区域.
其实就是obj.free
obj:=nil
的效果跟FreeAndNil()一模一样。
我也不知道你是不是想要这样的回答。呵呵
 
var
sList:TStringList;
begin
sList:=TStringList.Create;
sList.Free //更成FreeAndNil(sList)看看,ShowMessage结果不一样,区别仅在于此
ShowMessage(IntToStr(Integer(sList)));
end;
 
我知道区别,因小弟平常用的不多,所以想知道一般在什么情况下使用它们。

比如说一个全局的对象,什么时候Free或FreeAndNil?
 
如果你不判断对象是不是nil,那么Free和FreeAndNil没什么区别,但Free后对象不一定就=nil了,还是用FreeAndNil吧,准没错。
 
FreeAndNil能够在Free之后将对象变量本身清零,能够避免对同一个对象的多次释放。如
果你的对象处理逻辑非常简单明确,只会被释放一次,那么Free就够了。如果逻辑中有不确
定因素,导致不一定总是让对象在一个特定的场景中被释放,而需要多个场景联合才能正确
的释放,那就用FreeAndNil确保不被多次释放。
另外,FreeAndNil之后,可以让程序很容易的检查对象变量的有效性(我们一般用s<>nil
来判定)——当然,如果确实存在“不知道”对象是否有效的程序段的话。
 
有的只能Free,有的只能=nil,有的可以同时操作,
 
在这里我想指出shangshang和creation-zy的错误,
不要望文生义,
FreeAndNil不是先free再设置nil,
而是在释放对象前先将对象赋nil以清除对象的引用。
对于要在不同模块生成释放,
需要多次重用的动态对象,
使用前先做判断是必要的,
做好设计是关键。

以前刚学c++从过程化到接触对象,流这些东西时,
觉得大开眼界,
因为动态对象开始也吃了不少亏,
花了不少时间研究,
查阅了大量资料,
把这些弄清楚了是大有好处的。
FreeAndNil建议看下sysutils.pas
包括里面注释都研究下,
有些内嵌汇编如果没有基础可以先不管他。
 
to kkyy:
能再详细些吗?
 
感谢stlont ,我回答的不太全面。找了几句关于分析FreeAndNil的实现的评论
(转帖自lid=1547596)

先置nil 和先Free后置nil的实现方法
两种处理方法是有区别的,
对于第一种,则能保证对象指针被置空,
但对于第二种,如果引用的对象已经不存在,那么会出现异常,
或者说一个对象被销毁时发出异常,那么对象指针则仍然是原来的值
同时指针也不能被置空了,

FreeAndNil是用于将不再使用的对象释放并将变量置空,这样在下次误用时必将暴露出错误
,一个空悬的指针可能引起古怪的程序行为导致调试除错困难,而一个空指针引起的问题就
确定的多。
第一种实现可以保证不再使用的对象指针置空,所以即使函数中发生异常,也可以带来更加
安全的结果。
这是一种防错性的程序设计技术的运用。[:)]
 
更不明白了。 -_-!
 
感谢stlont兄:) 如果Borland将函数名改为NilAndFree那就不会有歧义了,哈哈 :P

>>更不明白了
我晕。看来老兄似乎对“对象变量”还没有一个清晰的概念啊... 建议面壁读书——先把
这关给过了吧。
推荐:DELPHI的原子世界 http://www.delphibbs.com/delphibbs/dispq.asp?lid=1396991
 
俺也不太懂,只不过经过几次尝试,知道这一点
FreeAndNil(Object);
等同于
Object.Free;
Object:= nil;
如果Object.Create后,Assigned(Object)=True,Object.Free后,Assigned(Object)=True,此时虽然Object已Free,但Object指针并没有nil,如果想要Assigned(Object)=False,则还需要Object:=nil则行,但用FreeAndNil(Object)一句就行了。
呵呵,这只是俺的一点小测试,希望能对你有所帮助。
 
对于你要释放的对象如果别的地方还需要判断它是否=nil,则释放的时候用freeandnil,否则就两者皆可
 
这是下面的我回的那个例子的延续:
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;

再加一个Button5:
procedure TForm1.Button5Click(Sender: TObject);
var
P: TObject;
begin
P:= TObject(Form2);
P:= nil;
P.Free;
end;

Button5的效果类似于Button2。。
关于这种TObject(Form2)转换,其内部怎么管理的偶不太明白。。。
请教。。。
 
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit2;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
if not Assigned(Form2) then
begin
Form2:= TForm2.Create(self);
Form2.show;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Form2:= nil;
Form2.Free;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Form2.Free;
Form2:= nil;
end;

end.

经过测试,先Free后Nil,和先Nil后Free的效果是不一样的。上面的是例子。
Button2按下后,Form2虽然已经没有了,但其窗体依然存在。不知道是为什么。。。
Button2按下后,Form2没有了,窗体也消失了。 OK 。
 
Form2:=nil
//仅清空了对象变量Form2,但它所指向的对象实例没有被释放,窗体还在
Form2.Free
//释放Form2——也就是nil——什么也没有发生
//应该用一个临时对象变量记录Form2的值,然后Form2:=nil;,再释放这个临时对象变量。


Form2.Free;
Form2:=nil;
//等效于FreeAndNil——如果Free时没有发生异常的话。
 
先将Form2 = nil清空了Form2的指向,那么接下来再操作Form2恐怕就不灵光了.
 
creation-zy 的第一个解释VeryGood。
 
那有Button2
 
后退
顶部