我想我遇到了一个棘手的情况。我需要能够释放一个记录字段的对象。如果它是一个类,我通常会在析构函数中编写清理代码。但是由于记录类型不能引入“析构函数”,那么如何调用TObject(字段).Free; ?
我预测会有两种类型的使用:
-
用新记录替换记录。
我认为这种用法很容易实现。由于记录是值类型,因此它们在赋值时被复制,因此我可以重载赋值运算符并释放旧记录拥有的对象。
( Edit:无法进行赋值重载。这对我来说是一个新信息..)
-
退出记录变量定义的范围。
我可以想到一个释放对象的私有方法,并且可以在范围激励上手动调用该方法。但是,这是同样的问题:如何让它变得更多recordly?这种行为有点像一个班级......
这是一个示例(显然不是预期用途):
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;
Assume,
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仍然保持其存在,导致内存泄漏......
如果记录中只有对象引用,那么编译器就无法帮助您。您全权负责该对象的生命周期。您不能重载赋值运算符,并且您不会收到任何范围终止的通知。
不过,您可以做的是添加一个保护接口来管理对象的生命周期。
TMyRecord = record
obj: TMyObject;
guard: IInterface;
end;
你需要确保TMyObject
通过引用计数来管理其生命周期。例如,通过派生自TInterfacedObject
.
当您初始化记录时,您将执行以下操作:
rec.obj := TMyObject.Create;
rec.guard := rec.obj;
此时,guard
记录的字段现在将管理对象的生命周期。
事实上,如果你想进一步推动这个想法,你可以构建一个专用的类来保护对象的生命周期。那么就不再限制你实施IInterface
在你的课堂上。网络上有很多示例来说明该技术。例如,我提供 Jarrod Hollingworth 的文章,标题为智能指针 http://members.adug.org.au/2011/12/05/smart-pointers/,巴里·凯利的标题是重新审视引用计数指针 http://blog.barrkel.com/2008/11/reference-counted-pointers-revisited.html。还有更多。这是老把戏了!
但请注意,这里是值类型和引用类型的奇怪混合体。从表面上看,记录是值类型。然而,这个类型的作用就像一种引用类型。如果记录中还有其他属于值类型的字段,那么情况会更加混乱。当您处理此类记录时,您需要非常注意这个问题。
从表面上看,在不了解更多有关您的设计的情况下,我倾向于建议您不要将对象引用放入记录中。它们更适合内部引用类型,即类。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)