How to free an object which is in a record?

限于喜欢 提交于 2019-12-04 02:56:07

If all you have in the record is an object reference, then you can't get the compiler to help you. You are in sole charge of the lifetime of that object. You cannot overload the assignment operator, and you don't get any notification of scope finalisation.

What you can do though is to add a guard interface that will manage the lifetime of the object.

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

You need to make sure that TMyObject manages its lifetime by reference counting. For example by deriving from TInterfacedObject.

When you initialise the record you do this:

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

At this point, the guard field of the record will now manage your object's lifetime.

In fact, if you want to push this idea further, you can build a dedicated class to guard the lifetime of objects. That then no longer constrains you to implement IInterface on your class. There are plenty of examples on the web that illustrate the technique. For example I offer Jarrod Hollingworth's article titled Smart Pointers, and Barry Kelly's titled Reference-counted pointers, revisited. There are many more out there. It's an old trick!

Note however, that what you have here is a strange hybrid of value type and reference type. On the face of it, records are value types. However, this one acts like a reference type. If you have other fields in the record that are value types then that would be even more confusing. You'll need to be very aware of this issue when you work with such a record.

On the face of it, without knowing more about your design, I'd be inclined to advise you not to put object references in records. They fit better inside reference types, i.e. classes.

I remember that someone created a class named TLifetimeWatcher. Basically, it looks like:

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;

// The (cleanup) proc will be executed in the destructor if assigned, otherwise the instance will be freed by invoking the Free method.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!