为什么要这样写?
procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;这样不行吗? 我经常这样用啊.
procedure FreeAndNil(var Obj: TObject);
begin
  Obj.Free;
  Obj := nil;
end;

解决方案 »

  1.   

    不知道,也许是为了避免直接Free时出现异常,造成Obj这个引用不能nil吧,瞎猜的。
    //这是Indy9 IdGlobal.pas中的写法procedure FreeAndNil(var Obj);
    var
      P: TObject;
    begin
      if TObject(Obj) <> nil then begin
        P := TObject(Obj);
        TObject(Obj) := nil;  // clear the reference before destroying the object
        P.Free;
      end;
    end;
      

  2.   

    大概是
    后者调用:FreeAndNil(TObject(Obj));
    前者调用:FreeAndNil(Obj);
    后者更简洁吧
      

  3.   

    不知道, 可能是先清除引用, 使它在Free之前取消关联与它相关的通知事件, 提高Destroy的效率及引用错误. 哈哈..
      

  4.   

    procedure FreeAndNil(var Obj);
    var
    P: TObject;
    begin
    if TObject(Obj) <> nil then begin
    P := TObject(Obj);
    TObject(Obj) := nil; // clear the reference before destroying the object
    P.Free;
    end;
    end;indy真是多此一举,Free本身就会判断对象指针是否nil;我之所以有这一问是因为Delphi所有的对象都是基于Tobject的,完全没必要用一个
    无类型变量作参数啊.
    估计他之所以设个中间变量,是以防万一,怕在Free的过程中其他代码又调用该对象,
    这样一来就线程安全了? 
    不解.
      

  5.   

    >>估计他之所以设个中间变量,是以防万一,怕在Free的过程中其他代码又调用该对象,
    >>这样一来就线程安全了? 把原来的Obj设为nil,对多线程来说,启不是更加不好?
      

  6.   

    还有一种可能,就是利用 Temp := TObject(Obj); 测试一下Obj,看看它是不是真的是个TObject,
    因为指针不见得都是TObject.
      

  7.   

    >>把原来的Obj设为nil,对多线程来说,启不是更加不好?也对,没理由把Obj直接传给其他线程,都是传址,这样一来线程安全起不到任何作用了.
      

  8.   

    还有一种可能,就是利用 Temp := TObject(Obj); 测试一下Obj,看看它是不是真的是个TObject,
    因为指针不见得都是TObject.那第二个方法不更好?
      

  9.   

    (var Obj);
    传进来的是一个没有类型的,要先转为 TObject;  Temp := TObject(Obj);
      Pointer(Obj) := nil; //这样也可以减少对Obj的引用
      Temp.Free;
      

  10.   

    Pointer(Obj) := nil; //这样也可以不减少对Obj的引用, 上面说错了
      

  11.   

    ==> Pointer(Obj) := nil; //这样也可以不减少对Obj的引用, 上面说错了
    为什么要不让它减少对Obj的引用呢?
      

  12.   

    procedure FreeAndNil(var Obj);
    var
      Temp: TObject;
    begin
      Temp := TObject(Obj);
      Pointer(Obj) := nil; //在释放对象前清除对其的引用
      Temp.Free;
    end;
      

  13.   

    其实要搞清楚free和nil的概念就明白了,free是释放指针指向的内存,nil是把指针变量本身的值,也就是内存地址变成nil,避免它成为野指针。
    对C语言的指针清楚的话,这个应该不难理解。
    对于局部变量,大部分情况只要free就可以,局部变量在函数运行结束会被自动释放的,和普通的变量没有区别。但是如果你没有free,那么只有指针变量本身被释放,指针指向的地址则成了内存泄漏。
      

  14.   

    两种写法应该是一样的效果。楼上的讨论的关于线程的说法似乎有些道理,先用temp保存引用,再清除外部引用,free时在线程上就安全了。
      

  15.   

    to ppayun(~云彩):大哥,你说了那么多,到底说明了什么呢?
    谁不知道“free是释放指针指向的内存,nil是把指针变量本身的值”,
    问题是Borland写 FreeAndNil 这个函数时为什么要那样写?
    而不是通常的 xxx.Free; xxx:=nil; 这种写法。
      

  16.   

    看半天没搞懂什么意思,哪个superman 来点详细的
      

  17.   

    我估计在Obj.Free;句之后,在Obj := nil;之前可能因为多线程应用程序,别的地方用了 obj 就会出地之引用错误。多半是因为这样。
      

  18.   

    >>指针不见得都是TObject
    帮助中说:“Obj must be an instance of a TObject descendent class”,我想这个写法只是确保可以得到一个干净的“返回值”,甚至在obj.free出错时,
    它相当于
    try
      obj.free
    finally
      obj=nil;
    end;
      

  19.   

    procedure FreeAndNil1(var Obj);
    var
    Temp: TObject;
    begin
    Temp := TObject(Obj);
    Pointer(Obj) := nil;
    Temp.Free;
    end;
    其实意思和
    procedure FreeAndNil2(var Obj: TObject);
    begin
    Obj.Free;
    Obj := nil;
    end;
    是一样的为什么要这样写?主要是为了避开类型检查传递任意类型的对象给FreeAndNil1都能通过编译
    但是FreeAndNil2只能传递TObject,其它类型都不可以