在这里,我有一个棘手的情况,我猜。 我需要能够释放的对象,它是一个记录的字段。 我通常会写清理代码在析构函数,如果它是一个类。 但由于记录类型不能引入“析构函数”,怎么会是可以调用TObject的(场)。自由; ?
将会有两种用法我预测:
与更换新的记录。
我觉得这种用法很容易实现。 由于记录是值类型,所以他们是在分配复制,我可以重载分配操作员,并释放被老唱片拥有的对象。
( 编辑:分配超载无法这是给我一个新的信息...。)
离开记录变量定义为其中的范围。
我认为释放的对象,并且此方法可以在范围激发手动调用私有方法。 但是,在这里是同样的问题:如何使之更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;
假设,
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
在你的类。 有很多是说明该技术在网络上的例子。 比如我提供贾罗德·霍林沃思的文章,题为智能指针 ,以及巴里·凯利的标题引用计数指针,重新审视 。 还有更多的在那里。 这是一个老把戏!
但是请注意,你在这里是什么值类型和引用类型的一个奇怪的混合体。 在它面前,记录是值类型。 然而,这一个的作用就像一个引用类型。 如果您在记录的其他字段是值类型,那么这将是更加令人困惑。 你需要非常了解这个问题,当你与这样的记录工作的。
在它面前,不知道更多关于你的设计,我会倾向于劝你不要把对象引用的记录。 他们装进引用类型,即类更好。
我记得有人创建了一个名为TLifetimeWatcher类。 基本上,它看起来像:
TLifetimeWatcher = class(TInterfacedObject)
private
fInstance: TObject;
fProc: TProc;
public
constructor Create(instance: TObject); overload;
constructor Create(instance: TObject; proc: TProc); overload;
destructor Destroy; override;
end;
//的(清理)PROC将在析构函数,如果分配被执行,否则实例将通过调用方法免被释放。