Using Reference Counting
Go Up to Memory Management of Interface Objects
In this documentation, you will find a description of the reference counting for the interfaces supported by all Delphi compilers.
The Delphi compiler provides most of the IInterface memory management for you through its implementation of interface querying and reference counting. Therefore, if you have an object that lives and dies by its interfaces, you can easily use reference counting by deriving from TInterfacedObject. If you decide to use reference counting, then you must be careful to only hold the object as an interface reference and to be consistent in your reference counting. For example:
procedure beep(x: ITest); function test_func() var y: ITest; begin y := TTest.Create; // because y is of type ITest, the reference count is one beep(y); // the act of calling the beep function increments the reference count // and then decrements it when it returns y.something; // object is still here with a reference count of one end;
This is the cleanest and safest approach to memory management; and if you use TInterfacedObject it is handled automatically. If you do not follow this rule, your object can unexpectedly disappear, as demonstrated in the following code:
function test_func() var x: TTest; begin x := TTest.Create; // no count on the object yet beep(x as ITest); // count is incremented by the act of calling beep // and decremented when it returns x.something; // surprise, the object is gone end;
procedure beep(const x: ITest);
or
procedure beep(var x: ITest);These declarations generate smaller, faster code.
One case where you cannot use reference counting because it cannot be consistently applied is when your object is a component or a control owned by another component. In that case, you can still use interfaces, but you should not use reference counting because the lifetime of the object is not dictated by its interfaces.