我猜这里有一个棘手的情况.我需要能够释放一个记录字段的对象.我通常会在析构函数中编写清理代码,如果它是一个类.但是由于记录类型不能引入"析构函数",如何调用TObject(Field).Free; ?
我预测会有两种用法:
用新的记录替换记录.
我认为这种用法很容易实现.由于记录是值类型,因此它们在赋值时被复制,我可以重载赋值运算符并释放旧记录所拥有的对象.
(编辑:分配重载不能.这对我来说是个新信息..)
退出记录变量定义的范围.
我可以想到一个释放对象的私有方法,这个方法可以手动调用范围激励.但是,这是同一个问题:如何使它更具记录性?这种行为感觉就像一个班级......
这是一个示例(显然不是预期用途):
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;
Run Code Online (Sandbox Code Playgroud)
假设,
FAdditionalData:=TList<Pointer>.Crete;
Run Code Online (Sandbox Code Playgroud)
通过公开访问字段,在记录构造函数中调用或在记录变量范围内手动调用
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;
Run Code Online (Sandbox Code Playgroud)
在退出ButtonClick范围后,rec不再是,但TList仍然保持其存在,导致内存泄漏...
Dav*_*nan 11
如果记录中的所有内容都是对象引用,那么您无法让编译器帮助您.您完全负责该对象的生命周期.您不能重载赋值运算符,也不会获得范围终结的任何通知.
您可以做的是添加一个可以管理对象生命周期的保护接口.
TMyRecord = record
obj: TMyObject;
guard: IInterface;
end;
Run Code Online (Sandbox Code Playgroud)
您需要确保TMyObject通过引用计数来管理其生命周期.例如,通过派生而来TInterfacedObject.
初始化记录时,您执行以下操作:
rec.obj := TMyObject.Create;
rec.guard := rec.obj;
Run Code Online (Sandbox Code Playgroud)
此时,guard记录的字段现在将管理对象的生命周期.
实际上,如果你想进一步推动这个想法,你可以构建一个专用的类来保护对象的生命周期.然后,这不再限制您IInterface在课堂上实施.网上有很多例子说明了这种技术.例如,我提供了Jarrod Hollingworth的文章,名为Smart Pointers,以及Barry Kelly的标题为Reference-counting指针,重新审视.那里还有很多.这是一个老技巧!
但请注意,您在此处拥有的是值类型和引用类型的奇怪混合.从表面上看,记录是价值类型.但是,这个就像一个引用类型.如果记录中有其他字段是值类型,那么这将更加令人困惑.使用此类记录时,您需要非常了解此问题.
从表面上看,在不了解您的设计的情况下,我倾向于建议您不要将对象引用放在记录中.它们更适合引用类型,即类.
| 归档时间: |
|
| 查看次数: |
4342 次 |
| 最近记录: |