如何更改析构函数以处理共享对象实例?
示例:
type
TAddress = class
private
FStreet : String;
public
property street: String read FStreet write FStreet;
end;
TContract = class
private
FAddress : TAddress;
public
property address: TAddress read FAddress write FAddress;
destructor Destroy; override;
end;
Array_Of_TContract = array of TContract;
TCustomer = class
private
FContracts : Array_Of_TContract;
public
property contracts: Array_Of_TContract read FContracts write FContracts;
destructor Destroy; override;
end;
implementation
destructor TCustomer.Destroy;
var
I: Integer;
begin
for I := 0 to System.Length(FContracts)-1 do
SysUtils.FreeAndNil(FContracts[I]);
System.SetLength(FContracts, 0);
inherited Destroy;
end;
destructor TContract.Destroy;
var
I: Integer;
begin
SysUtils.FreeAndNil(FAddress);
inherited Destroy;
end;
begin
Try
//address
myAddress := TAddress.Create;
myAddress.street := 'My Street';
//First contract
SetLength(myContracts, Length(myContracts)+1);
FirstContract := TContract.Create;
FirstContract.address := myAddress; //<-
myContracts[0] := FirstContract;
//Second contract
SetLength(myContracts, Length(myContracts)+1);
SecondContract := TContract.Create;
SecondContract.address := myAddress; //<-
myContracts[1] := SecondContract;
//Single customer
myCustomer := TCustomer.Create;
myCustomer.contracts := myContracts;
myCustomer.Free;
self.Close;
Except
On e: exception do begin
ShowMessage(e.Message);
end;
End;
end;
释放myCustomer(和内存泄漏)时,结果是指针操作无效。
(在我的情况下,不为每个TContract创建单独的TAddress对象)
答案 0 :(得分:1)
处理此类情况的最佳方法取决于应用程序的结构。基于该示例,我将所有地址添加到通用对象列表,然后将地址引用传递给TContract
的实例。对于合同,如果它们不是唯一的,您可以使用类似的方法。
替代方法是使用接口作为地址,然后将其分配给合同实例,最后将其取消。
第三种选择是复制作业。我认为这是处理这种情况的最低效的方法,但它保证可以在任何情况下工作。
希望这些提出了一些想法。
答案 1 :(得分:0)
我不希望在联系人之间共享相同的地址实例。但由于代码是自动生成的,我想这不是一个选项。
您可以跟踪已经释放的引用:
AlreadyFreed := TList <Pointer>.Create;
for I := 0 to System.Length(FContracts)-1 do
begin
if not AlreadyFreed.Contains(FContracts[I]) then
begin
FContracts[I].Free;
AlreadyFreed.Add(Pointer(FContracts[I]));
end;
end;