制作要在以后使用的对象的副本

Lui*_*ves 0 delphi object

我有一个包含以下类的组件:

TResp=Class
...

TRespostasPendentes = class(TObjectList)
   private
      fSaldoAPagar : Double;
      function GetSaldoRestante : Double;
      function GetTotalPago : Double;
      function GetTotalDesconto : Double;
   protected
      procedure SetObject (Index: Integer; Item: TResp);
      function GetObject (Index: Integer): TResp;
   public
      function Add (Obj: TResp): Integer;
      procedure Insert (Index: Integer; Obj: TResp);
      property Objects [Index: Integer]: TResp
        read GetObject write SetObject; default;

      property SaldoAPagar   : Double read fSaldoAPagar write fSaldoAPagar ;
      property TotalPago     : Double read GetTotalPago ;
      property TotalDesconto : Double read GetTotalDesconto ;
      property SaldoRestante : Double read GetSaldoRestante ;
   end;
Run Code Online (Sandbox Code Playgroud)

我需要在a中复制一个对象,TRespostasPendentes以便在它被释放后使用.

原始类不实现该Assign()方法.

我尝试了下一个代码,但在释放副本时出现了访问冲突.

我究竟做错了什么?

我不能改变原来的课程.

RespostasPendentes:=TRespostasPendentes.Create;
//Here I fill some properties of RespostasPendentes
RP:=TRespostasPendentes.Create;
try
  RP.Assign(RespostasPendentes);
  RespostasPendentes.Free; 
finally
  RP.Free; -->Access Violation
end;
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

TObjectList.OwnsObjects默认情况下,该属性为True.TObjectList 继承Assign()TList,默认情况下只复制源列表中的指针.

因此,您最终得到两个TObjectList"拥有"同一组对象的对象,因此当一个列表尝试释放另一个列表已释放的相同对象时,您将获得AV.

要防止第一个列表释放对象,您需要:

  • OwnsObjects对象指针复制到第二个列表后,将第一个列表设置为False.

    RespostasPendentes := TRespostasPendentes.Create;
    // ...
    RP := TRespostasPendentes.Create(False); // <-- False initially in case Assign() fails...
    try
      RP.Assign(RespostasPendentes);
      RespostasPendentes.OwnsObjects := False; // <-- add this 
      RP.OwnsObjects := True; // <-- take ownership of the copied pointers
      RespostasPendentes.Free; 
      // use RP as needed...
    finally
      RP.Free;
    end;
    
    Run Code Online (Sandbox Code Playgroud)
  • Extract() 来自第一个列表的对象指针使其放弃所有权而不释放对象,然后将指针添加到第二个列表.

    RespostasPendentes := TRespostasPendentes.Create;
    // ...
    RP := TRespostasPendentes.Create;
    try
      RP.Capacity := RespostasPendentes.Count;
      while RespostasPendentes.Count > 0 do
      begin
        Obj := RespostasPendentes.Objects[0];
        RespostasPendentes.Extract(Obj); // <-- remove ownership
        try
          RP.Add(Obj); // <-- take ownership
        except
          Obj.Free;
          raise;
        end;
      end;
      RespostasPendentes.Free; 
      // use RP as needed...
    finally
      RP.Free;
    end;
    
    Run Code Online (Sandbox Code Playgroud)