New does the following:
- Allocate memory for the new object with a call to
GetMem . - Initialize any managed fields, such as strings, interfaces, dynamic arrays, etc.
Dispose cancels this:
- Complete managed fields.
FreeMem memory by calling FreeMem .
Note that both New and Dispose are internal functions . This means that the compiler has additional knowledge about them and can change the way they are implemented depending on the type in question.
For example, if a type has no managed fields, then New optimized into a simple GetMem call. If the type has managed fields, then New is implemented with a call to System._New , which performs the above actions.
The implementation of Dispose almost the same. A simple call to FreeMem for non-managed types and a call to System._Dispose otherwise.
Now System._New is executed as follows:
function _New(Size: NativeInt; TypeInfo: Pointer): Pointer; begin GetMem(Result, Size); if Result <> nil then _Initialize(Result, TypeInfo); end;
Please note that I just showed the PUREPASCAL option for simplicity. Calling GetMem quite simple. The call to System._Initialize much more active. This uses the TypeInfo argument to find all the managed types contained in the object and initialize them. This is a recursive process, because, for example, a record can contain elements that are themselves types of structure. You can see all the gory details in the RTL source.
As for System._Dispose , it calls System._Finalize and then FreeMem . And System._Finalize very similar to System._Initialize , except that it completes the managed types, rather than initializing them.
This has long been a bit of a performance-sensitive Delphi user error that System._Initialize and System._Finalize implement this way on top of information like System._Finalize . Types are known at compile time, and the compiler can be written to enable initialization and termination, which will improve performance.
source share