Posted: Aug 13, 2010 1:42 am
by Calilasseia
I always understood the process of instantiating and de-instantiating objects to be performed by entities outside the objects in question. The new and delete operators achieve this. An object can contain within it a constructor method, which is used to tell the new operator how to initialise an object if the creation of an instance is accompanied by relevant initialisation data, and which the new operator calls after it has allocated memory for that object, set up the pointers to the methods, and provided a pointer to the object for the object reference variable to contain. In its simplest form, the delete operator simply returns the allocated memory to the operating system's free list, and sets the object reference variable to some suitable 'null' value to indicate that it's no longer pointing to an object.

More sophisticated versions of delete allow for a destructor method to be called, whose job is to perform tasks that may be necessary before the object can be freed and dereferenced. For example, if the object being created contains within it yet more object reference variables that can contain pointers to other instances of the same object class, facilitating, for example, the construction of a doubly linked list, then it may be necessary to include a destructor method for the class, that checks to see if the instance is currently linked into a doubly linked list, and if so, unlink it from the list before it is deleted. Without such a destructor method, reliance upon the programmer to remember to unlink every linked object from the list introduces an extra source of potential bugs, whereas with the destructor method in place, once it's working of course, the programmer is no longer required to remember to unlink objects intended for deletion from the list, because the destructor method, once it's working, handles that on the programmer's behalf. The programmer can then get on with the business of actually using the objects for something. In the doubly linked list scenario, the constructor method would also provide some means of adding a newly instantiated object to an existing list, or, if the object being instantiated is the first in the list, provide some means of handling this case in a consistent fashion.

Different languages have different syntaxes for handling all of this, of course.

One big problem that needs to be addressed concerns garbage collection. In an environment where garbage collection is provided as an automatic feature of the run-time environment, problems can arise with respect to ensuring that destructors are called, if the programmer simply dereferences the entire list in one fell swoop, using the above doubly linked list example. indeed, there's an entire body of literature on the subject of garbage collection, because ensuring the consistent release of allocated resources (memory, file handles etc) is time consuming, and conflicts with the need to minimise the impact of the run-time environment's ancillary services upon the executing program. Balancing these requirements is one of those particularly difficult computer science problems, and finding a consistent, secure and fast garbage collection method is one of those Holy Grails of computer science that may never be achieved. All of which is compounded yet again when you consider programs that are multi-threaded, even if the threads are actually executed on one processor via the multitasking executive - it's possible, if you're not careful, for one thread to specify that it wants to delete an object at the same time as another thread wants to press that object into use, and synchronising usage versus deletion of objects across threads in a multitasking environment is another nice minefield for the unwary, made all the more hilarious when one implements multithreading on a genuine multiprocessor environment, where the threads are given their own processor to run on.