(I added this answer because IMHO others where not completed)
Method 2 is correct.
Method 1, if you never call it, because there is a hidden parameter to invoke the constructor that may not match the iniatialize proper: in fact, NewInstance
is a pseudo-virtual method for each class!
Actually there is a hidden boolean
parameter when calling the constructor (register EDX
, since EAX
= class). As stated in the official documentation :
Constructors and destructors use the same calls as other methods, except that the optional flag parameter boolean
is passed specify the context for calling the constructor or destructor.
A value of False
in the constructor invocation flag parameter indicates that the constructor was called through an instance of the object or using an inherited keyword. In this case, the constructor behaves like a regular method. A value of True
in the flag parameter of the constructor call indicates that the constructor was called through the reference class. In this case, the constructor creates an instance of the class
specified by Self
, and returns a reference to the newly created object in EAX
.
In particular, when calling this class, the class will not call the _ClassCreate
function. This may not initialize the class if the class is not created using the default NewInstance
function. In fact, this function is inserted into the VMT class: in some rare cases, it can be overloaded (for example, to provide another memory allocation pattern - it can be a garbage collector or some optimizer with speed optimization). Therefore, calling InstanceClass.NewInstance
directly may be erroneous, in some cases with borders.
function _ClassCreate(AClass: TClass; Alloc: Boolean): TObject; asm ... TEST DL,DL JL @@noAlloc CALL dword ptr [EAX].vmtNewInstance @@noAlloc: ...
Therefore, calling InstanceClass.NewInstance
directly must be done on purpose only if you want to cancel two overridden vmtNewInstance / vmtFreeInstance
(in which case you may also NOT call .Free / .Destroy
, but you have a free function memory). So: never call NewInstance
, but constructor
, as it was developed and documented by Embarcadero (and the FreePascal team, by the way), if you do not need to make some internal low-level settings.
NEVER use method 1 to create an object! It may work 99.9% of the time, but it may crash in some cases or with the compiler / RTL extension in the future (e.g. garbage collector). Even if the VCL sometimes uses NewInstance
, you should not use it - I would prefer this method to be protected.