基础问题啊,不太懂,请大家指点一下。
对象作为函数的指针是不是个指针?
例如我有一个类TMyClass,其有一个函数,GetDataSet,返回值是其内部创建的一个 TDataSet对象我在类外,创建一个TDataSet变量ds1,获得这个函数的返回值.
请问,这个ds1是个指针吗?怎么释放?只要ds1:=nil就可以了吗?会不会造成内存泄漏?(我不会怎么 评价程序性能和 内存泄漏情况)
请高手指点一下。

解决方案 »

  1.   

    半夜高手都不会来了,俺来呻吟两句吧
    //如果GetDataSet返回的是个非对象的成员变量(TDataSet对象),
    //那么接受该返回值的地方应该负责销毁该对象。例如
    function 某类.GetDataSet:TDataSet;
    var
      ds:TDataSet;
    begin
      ds:=TDataSet.Create(nil);
      result:=ds; // 返回局部变量(Tdataset对象)的引用(指针)
    end;// 调用处
    ....
    var
     _ds:TDataSet;
     obj:某类;
    begin
     obj:=某类.Create;
     _ds:=obj.GetDataSet; // _ds接收GetDataSet返回的dataset对象,把_ds指针指向GetDataSet函数中创建的TDataset对象ds
    // 。。
     _ds.free; // 如果此时不销毁_ds,就没机会销毁了,内存泄露。
     obj.free;
    end;// 如果 某类.GetDataSet 函数返回的是某类的成员变量,
    // 那么只要在某类的析构函数做free Tdataset对象即可,例如type 某类 = class
    private
     FDS:Tdataset;
    public
     function GetDataSet:TDataset;
     constructor Create;
     destructor  Destory;override;
    end;implementationconstructor 某类.Create;
    begin
      // 构造函数中创建该 TDataset对象
      FDS:= TDataSet.Create(nil); 
    end;destructor 某类.Destory;
    begin
      FDS.Free; // 析构函数中销毁该 TDataset对象
      inherited;
    end;function 某类.GetDataSet:TDataSet;
    begin
      result:= FDS; // 直接返回一个TDataSet对象
    end;。。// 调用处
    ....
    var
     _ds:TDataSet;
     obj:某类;
    begin
     obj:=某类.Create;
     _ds:=obj.GetDataSet; // _ds接收GetDataSet返回的dataset对象,
                          // 即把_ds指针指向GetDataSet函数中创建的TDataset对象ds
    // 。。
     obj.free; // 某类对象销毁时就能清理一切了
    end;
    //所以实际上,你这种GetDataSet的函数应该直接定义成一个某类的一个属性更方便,例如type 某类 = class
    private
     FDS:Tdataset;
    public
     function GetDataSet:TDataset;
     constructor Create;
     destructor  Destory;override;
     property MyDataSet:TDataSet read FDS;// 定义一个名为MyDataSet的只读属性
    end;。
    // 调用处
    ....
    var
     _ds:TDataSet;
     obj:某类;
    begin
     obj:=某类.Create;
     _ds:=obj.MyDataSet; // 直接通过某类的对象的属性来得到这个Tdataset
     // 。。
     obj.free; // 某类对象销毁时就能清理一切了
    end;
      

  2.   

    delphi中的指针实际更类似c\c++中的引用,在《delphi in a nutshell》(就是那本封面印着一个很像狮子的动物)中记得有讲到delphi中指针和引用在底层的细微区别,得回头翻书。但在delphi中一般可以混淆引用和指针的区别。delphi中所有的类的实例都是在栈中创建的,自己创建的就得明确自己何时何处是否销毁了它。类的实例的赋值都是指针的复制。
    除了指针(引用)类型,还有就是值类型的,例如record、一般类型(如integer、double...)
    所谓值类型,就是指它们的赋值就是复制本身而非指针var
     i,j:intege;
    begin
     i:=100;
     j:=i; // j=100, i=100, i,j各自都有自己的内存空间
    end;
    integer、double...这些属于一般类型,由编译器内部实现还有结构体record,如果TPoint,TRect这些都是结构体,它们之间的赋值也是值复制而非指针复制但有一些无需人工销毁的对象,它们自己管理自己的生命周期,如AnsiString对象,因为字符串是使用最多的一种类型,很多语言中都把字符串做了特别处理以方便使用,delphi中同样给字符串加入了引用计数,delphi自动维护一个Ansitring对象的引用计数,对该对象访问一次引用计数就+1,访问结束后计数-1,引用计数为0时就自动销毁,但同是字符串也有个例外,即WideString对象,它的赋值是复制一个对象的副本,因为WideString没有引用计数,它最初设计出来是为了兼容com的bstr类型的,Delphi2009之后加入了UnicodeString,这才真正是带引用计数的。这些区别是编译器内部实现的,当然初学者可以不用太多理会。
      

  3.   

    还有interface接口类型,可以通过接口实现c++的多重继承,使用接口还能通过引用计数自动管理生命周期,好处多多且代码量可以大幅缩小并降低内存泄露的风险,这个以后进阶再学吧 
      

  4.   

    LZ的方法 ,肯定 会造成内存泄露的。因为ds1 := nil 只是将此对象的内存地址变为nil,并没有将此对象销毁,必须使用ds1.free,才能释放。
      

  5.   

    要Free的.
    不过函数返回对象不推荐.
    推荐的做法是在外边创建对象,用参数传到函数中,用完就在外边释放.
    一般遵照谁来创建谁来释放的原则.
      

  6.   

    谢谢各位大人物的热心回答。特别是sololie写了那么多代码。