10

I'm somewhat new to Delphi, and this question is just me being curious. (I also just tried using it by accident only to discover I'm not supposed to.)

If you look at the documentation for TObject.InitInstance it tells you not to use it unless you're overriding NewInstance. The method is also public. Why not make it protected if the user is never supposed to call it?

Sentient
  • 1,102
  • 12
  • 29

3 Answers3

28

Since I was around when this whole Delphi thing got started back around mid-1992, there are likely several answers to this question. If you look at the original declaration for TObject in Delphi 1, there weren't any protected/private members on TObject. That was because very early on in the development of Delphi and in concert with the introduction of exceptions to the language, exceptions were allocated from a different heap than other objects. This was the genesis of the NewInstance/InitInstance/CleanupInstance/FreeInstance functions. Overriding these functions on your class types you can literally control where an object is allocated.

In recent years I've used this functionality to create a cache of object instances that are literally "recycled". By intercepting NewInstance and FreeInstance, I created a system where instances are not returned to the heap upon de-allocation, rather they are placed on a lock-free/low-lock linked list. This makes allocating/freeing instances of a particular type much faster and eliminates a lot of excursions into the memory manager.

By having InitInstance public (the opposite of which is CleanupInstance), this would allow those methods to be called from other utility functions. In the above case I mentioned, InitInstance could be called on an existing block of memory without having to be called only from NewInstance. Suppose NewInstance calls a general purpose function that manages the aforementioned cache. The "scope" of the class instance is lost so the only way to call InitInstance is of it were public.

One of these days, we'll likely ship the code that does what I described above... for now it's part of an internal "research" project.

Oh, as an aside and also a bit of a history lesson... Prior to the Delphi 1 release, the design of how Exception instances were allocated/freed was returned to using the same heap as all the other objects. Because of an overall collective misstep it was assumed that we needed to allocate all Exception object instances to "protect" the Out of memory case. We reasoned that if we try and raise an exception because the memory manager was "out of memory", how in the blazes would we allocate the exception instance!? We already know there is no memory at that point! So we decided that a separate heap was necessary for all exceptions... until either Chuck Jazdzewski or Anders Heijlsberg (I forget exactly which one), figured out a simple, rather clever solution... Just pre-allocate the out of memory exception on startup! We still needed to control whether or not the exception should ever actually be freed (Exception instances are automatically freed once handled), so the whole NewInstance/FreeInstance mechanism remained.

Allen Bauer
  • 16,657
  • 2
  • 56
  • 74
  • Nice to hear from someone who knows. I've stumbled upon this pre-allocated out of memory exception once, and I thought it was quite clever indeed. :) – GolezTrol Mar 20 '14 at 22:20
  • Hopefully you will one day return and make Delphi great again. – Gabriel Jun 26 '19 at 11:54
4

Well never say never. In the VCL too much stuff is private and not virtual as it is, so I kinda like the fact that this stuff is public.

It isn't really necessary for normal use, but in specific cases, you might use it to allocate objects in bulk. NewInstance reserves a bit of memory for the object and then calls InitInstance to initialize it. You could write a piece of code that allocates memory for a great number of objects in one go, and then calls InitInstance for different parts of that large block to initialize different blocks in it. Such an implementation could be the base for a flyweight pattern implementation.

Normally you wouln't need such a thing at all, but it's nice that you can if you really want/need to.

How it works?

The fun thing is: a constructor in Delphi is just some method. The Create method itself doesn't do anything special. If you look at it, it is just a method as any other. It's even empty in TObject!

You can even call it on an instance (call MyObject.Create instead of TMyObject.Create), and it won't return a new object at all. The key is in the constructor keyword. That tells the compiler, that before executing the TAnyClass.Create method, it should also construct an actual object instance.

That construction means basically calling NewInstance. NewInstance allocates a piece of memory for the data of the object. After that, it calls InitInstance to do some special initialization of that memory, starting with clearing it (filling with zeroes).

Allocating memory is a relatively expensive task. A memory manager (compiled into your application) needs to find a free piece of memory and assign it to your object. If it doesn't have enough memory available, it needs to make a request to Windows to give it some more. If you have thousands or even millions of objects to create, then this can be inefficient.

In those rare cases, you could decide to allocate the memory for all those objects in one go. In that case you won't call the constructor at all, because you don't want to call NewInstance (because it would allocate extra memory). Instead, you can call InitInstance yourself to initialize pieces of your big chunk of memory.

Anyway, this is just a hypotheses of the reason. Maybe there isn't a reason at all. I've seen so many irrationally applied visibility levels in the VCL. Maybe they just didn't think about it at all. ;)

Uli Gerhardt
  • 13,748
  • 1
  • 45
  • 83
GolezTrol
  • 114,394
  • 18
  • 182
  • 210
  • I think you need to talk about the fact that calls to InitInstance from outside the class would only ever occur if you were instantiating objects without calling constructors. – David Heffernan Mar 20 '14 at 20:02
  • I tried. Is this what you have in mind? It's just theory. I've never implemented anything like this, so I hope I got it right. ;) – GolezTrol Mar 20 '14 at 20:19
  • I don't agree with your final paragraph. You would call the constructor. It would call `NewInstance`. But you would have overridden `NewInstance` to return an object from the pool. I mean you could do it the way you said but then constructors would never run and surely it's desirable to be able to run constructors. The extension point for object pools is that you override `NewInstance`. And `FreeInstance`. – David Heffernan Mar 20 '14 at 20:19
  • 2
    And how does some rare constructed case justify to make a method public that you could have made protected which means it still is accessable? – Stefan Glienke Mar 20 '14 at 20:26
  • 1
    That would be appropriate if the question was how to best implement an object pool, but this question rather is a *possible* explanation of why InitInstance would be public, which is pointless if you (just) override NewInstance and FreeInstance to do some smart memory management. Besides, if you want to, you can still call the constructor, that is, the Create method of the instance. – GolezTrol Mar 20 '14 at 20:27
  • @StefanGlienke It's not accessible for other classes if it is protected. In the setup I described, a different class would probably do the memory management. – GolezTrol Mar 20 '14 at 20:28
  • 2
    You know the simple trick to access protected members do you? If you are smart enough to implement your own memory management around the memory manager one you would use that aswell. That is hardly the reason why this method is public – Stefan Glienke Mar 20 '14 at 20:32
  • 1
    @StefanGlienke I know that trick, but to me it feels like a hack, which only works because `protected` in Delphi isn't `strict protected`, and allows access by any code in the entire unit. And that's fine, if you need to, but if I can just call a method without having to resort to hacks like that, I'm a happy camper. Using your arguments, we could just skip `public` altogether, and let people hack (or 'trick') their way to every method they would like to call. – GolezTrol Mar 20 '14 at 20:38
  • Mhhhmhh and working around the usual behavior of objects of course is not a hack... There is a principle called information hiding. So only make things public that are meant to be used from the outside and InitInstance certainly is not of that kind. – Stefan Glienke Mar 20 '14 at 20:44
  • @Golez the question does not mention strict protected – David Heffernan Mar 20 '14 at 20:44
  • 1
    @DavidHeffernan Neither does my answer. And also it wasn't my intention to write and defend the greatest object pool implementation ever, nor to get involved in a heavy protected vs public discussion. And I don't mean to assert that this method should be public at all. I just tried to give *a possible/plausible* reason why they would have done this and how you could make use of it. I don't know the exact reason any more than anyone here. – GolezTrol Mar 20 '14 at 20:53
  • 2
    I know a company that exactly does this. They use so much memory, that they wanted to minimize the memory manager overhead and just allocated and initialized big blocks of objects this way. They do other heavy lifting as well, like dynamically building and patching VMTs. Not your average piece of code (: – Jeroen Wiert Pluimers Mar 20 '14 at 21:23
-1

It gives developers a way to create object not using NewInstance (memory from stack/memory pool)

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
APZ28
  • 997
  • 5
  • 4
  • Er, how would that work? Surely executing the constructor is going to lead to a call to `NewInstance`. It's overriding `NewInstance` that allows you to allocate from object pool. – David Heffernan Mar 20 '14 at 19:59