请问一个类变量在使用前是否必须要创建?
比如说
function Add(client:TClientInfo):boolean;
var
  tmpClient:TClientInfo;
begin
  tmpClient := client; //这里使用对不对?是否一定要
   //运行tmpClient := TClientInfo.Create后才能用?
end;

解决方案 »

  1.   

    function Add(client:TClientInfo):boolean;
    var
      tmpClient:TClientInfo;
    begin
      tmpClient := client; //这里使用对不对?是否一定要'
       //可以的因为
      //参数client:TClientInfo实际为一个指针,
       //运行tmpClient := TClientInfo.Create后才能用?
       //如果这样的话一定要使用完以后FREE否则要有泄露
    end;
      

  2.   

    不一定,它本质就是一个指针,如果Client这个实例已经创建,直接将指针指向Client,当然就不需要再分配空间了!
      

  3.   

    //参数client:TClientInfo实际为一个指针,
      

  4.   

    假如client这个实例已经被创建,则tmpClient不用create,如果没有则必须用了!
      

  5.   

    DELPHI所有的对象都是指针类型的。至于实例化,如楼上所说。
      

  6.   

    假如client这个实例已经被创建,则tmpClient不用create,如果没有则必须用了
    并且会出现泄露
      

  7.   

    那么类指针之间可否进行比较?比如:
    function TClientList.GetcommaText :string;
    var
      tmpClient:TClientInfo;
    begin
      Result:='';
      if fHead = nil then Exit;
      tmpClient := fHead;
      if fMutex.GetObject Then
      begin
        while (tmpClient.fNextClient <> fHead )  do   ///此行总是报错,请看以下注释
        begin
          Result:=Result + tmpClient.UserInfo.Name+'_ID='+inttostr(tmpClient.ClientID)+',';
          tmpClient := tmpClient.fNextClient;
        end;
        Result := Result + tmpClient.UserInfo.Name+ '_ID='+inttostr(tmpClient.ClientID);
        fMutex.ReleaseObject;
      end;
    end;
    ///注释
    TClientInfo = class
    ...
    ...
    Prev,Next:TClientInfo;
    end;
    这里fHead是一个TClientInfo的结构,内部还有两个Next,Prev都是指向TClientInfo结构的变量,用来做双向链表。
    加入结点是这样做的:函数传递一个clientinfo:TClientInfo结构的变量,是已建好的,并且有数据。函数中定义一个tmpClient:TCLientInfo,并创建,然后把clientInfo的数据全部拷贝到tmpClient中。判断fHead是否为空,为空则fHead指向tmpClient,并把Prev和Next都指向fHead。不为空则加到后面。
    如下:
    //<--------------------------------------------->
    //<-----------添加新结点------------------------>
    //<--------------------------------------------->
    { TClientList public Add }
    function TClientList.Add(client:TClientInfo;inds:PInteger=nil):boolean;
    var
      tmpClient:TClientInfo;
      ids:integer;
    begin
      Result := false;
      if client = nil then Exit;
      //获取全局唯一标识符
      if not fIndexs.Assign(@ids) then Exit;  //分配标识符
      client.fClientID := ids;
      if inds <> nil then inds^:=ids;         //返回标识符值
      tmpClient := TClientInfo.Create;
      tmpClient.Assign(client);    //复制client所有值到tmpClient
      if fMutex.GetObject then    //抢占互斥
      begin
        if fHead = nil then
        begin
          fHead := tmpClient;
          fHead.fNextClient := fHead;
          fHead.fPrevClient := fHead;
        end
        else
        begin
          fHead.fPrevClient.fNextClient := tmpClient;
          tmpClient.fPrevClient := fHead.fPrevClient;
          fHead.fPrevClient := tmpClient;
          tmpClient.fNextClient := fHead;
        end;
        fMutex.ReleaseObject;  //释放互斥
        Result:=true;
        if Assigned(fOnListChange) then 
          fOnListChange(self);
      end
      else
        tmpClient.Free;  //如果抢夺互斥不成功,则放弃添加。
    end;添加过程没有发生过问题,不知道代码方面是否还有其它错误。但上面的GetCommaText的那一行总是报错。
    我的程序其实是这样的:当有客户连入时,获取客户信息后加入ClientList中,fHead是ClientList的一个私有成员。属于TClientInfo类变量。也就是当有客户连入时,就发生了GetCommaText里的错误。但令我不解的是,我用按钮模拟生成客户加入时就没有任何问题了。
      

  8.   

    我的结点删除代码有很严重的问题:
    procedure TClientList.Delete(clientID:integer);
    var
      tmpClient:TClientInfo;
      tmpPrev:TClientInfo;
      tmpNext:TClientInfo;
      ids:integer;
     begin
      if clientID <0  then Exit;
      if Pointer(fHead) = nil then   Exit;
      if fMutex.GetObject then
      begin
        tmpClient := fHead;
        ids:=tmpClient.fClientID; //保存标识符以便稍后释放
        //查找结点位置
        while (tmpClient.fNextClient <> fHead) and (tmpClient.fClientID <> clientID) do
         tmpClient := tmpClient.fNextClient;
        
    //删除
        if tmpClient.fClientID  = clientID then
        begin
          tmpPrev:=tmpClient.fPrevClient;
          tmpNext:=tmpClient.fNextClient;
          if tmpClient = fHead then
          begin
            fHead := tmpNext;
          end;      
          tmpPrev.fNextClient := tmpNext;
          tmpNext.fPrevClient := tmpPrev;    //执行到这里就出问题了。
          tmpPrev:=nil;
          tmpNext:=nil;  
          FreeAndNil(tmpClient);    //标注2    end;
        //释放互斥和标识符
        fMutex.ReleaseObject;
        fIndexs.Release(ids);
        //触发事件
        if Assigned(fOnListChange) then
          fOnListChange(self);    
      end;
    end;
    当结点只有一个时,删除过程中,执行到上面的地方时,监视窗口里显示出tmpNext和tmpPrev是inaccessible due to optimization,而且下面两句未执行就跳到标注2了。
    当执行到标注2结束时,发现fHead仍然有值,但其中有一个指向TUserInfo类的结构地址发生了变化。按我的意思,应该是:由于只有一个结点,故不管怎么样,tmpClient总是指向fHead的,执行标注2后类被释放,fHead应该不再有值的。为什么还会有值,而且值有部分发生了变化?