gpt4 book ai didi

delphi - 如何释放记录中的对象?

转载 作者:行者123 更新时间:2023-12-03 14:43:18 27 4
gpt4 key购买 nike

我猜我遇到了一个棘手的情况。我需要能够释放一个记录字段的对象。如果它是一个类,我通常会在析构函数中编写清理代码。但由于记录类型不能引入“析构函数”,那么如何调用 TObject(Field).Free; 呢?

我预测会有两种类型的使用:

  1. 用新记录替换该记录。

    我认为这种用法很容易实现。由于记录是值类型,因此它们在赋值时被复制,因此我可以重载赋值运算符并释放旧记录拥有的对象。

    (编辑:无法进行赋值重载。这对我来说是一个新信息..)

  2. 退出记录变量定义的范围。

    我可以想到一个释放对象的私有(private)方法,并且可以在范围激励上手动调用该方法。但是,这是同样的问题:如何使其更加记录?这种行为有点像一个类(class)......

这是一个示例(显然不是预期用途):

TProperties = record
... some other spesific typed fields: Integers, pointers etc..
FBaseData: Pointer;

FAdditionalData: TList<Pointer>;
//FAdditionalData: array of Pointer; this was the first intended definition
end;

假设,

FAdditionalData:=TList<Pointer>.Crete;

在记录构造函数中调用或通过公开访问字段在记录变量范围中手动调用

procedure TFormX.ButtonXClick(Sender: TObject);
var
rec: TProperties;
begin
//rec:=TProperties.Create(with some parameters);

rec.FAdditionalData:=TList<Pointer>.Create;

//do some work with rec
end;

退出 ButtonClick 范围后,rec 不再存在,但 TList 仍然保留其存在,这会导致内存泄漏...

最佳答案

如果记录中只有对象引用,那么编译器就无法帮助您。您全权负责该对象的生命周期。您不能重载赋值运算符,并且您不会收到任何范围终止的通知。

您可以做的是添加一个保护接口(interface)来管理对象的生命周期。

TMyRecord = record
obj: TMyObject;
guard: IInterface;
end;

您需要确保 TMyObject 通过引用计数来管理其生命周期。例如,通过从 TInterfacedObject 派生。

当您初始化记录时,您将执行以下操作:

rec.obj := TMyObject.Create;
rec.guard := rec.obj;

此时,记录的 guard 字段将管理对象的生命周期。

事实上,如果你想进一步插入这个想法,你可以构建一个专用的类来保护对象的生命周期。这样就不再限制您在类上实现 IInterface 了。网络上有很多示例来说明该技术。例如,我提供 Jarrod Hollingworth 的文章,标题为 Smart Pointers ,巴里·凯利的标题为 Reference-counted pointers, revisited 。还有更多。这是老把戏了!

但是请注意,这里是值类型和引用类型的奇怪混合体。从表面上看,记录是值类型。然而,这个类型的作用就像一种引用类型。如果记录中还有其他属于值类型的字段,那么情况会更加困惑。当您处理此类记录时,您需要非常注意这个问题。

从表面上看,在不了解更多有关您的设计的情况下,我倾向于建议您不要将对象引用放入记录中。它们更适合内部引用类型,即类。

关于delphi - 如何释放记录中的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12861268/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com