我有一个包含以下类的组件:
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)
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)