Why is the destructor not called in operator delete?

You are misusing operator new and operator delete. These operators are allocation and deallocation functions. They are not responsible for constructing or destructing objects. They are responsible only for providing the memory in which the object will be placed.

The global versions of these functions are ::operator new and ::operator delete. ::new and ::delete are new/delete-expressions, as are new/delete, differing from those, in that ::new and ::delete will bypass class-specific operator new/operator delete overloads.

The new/delete-expressions construct/destruct and allocate/deallocate (by calling the appropriate operator new or operator delete before construction or after destruction).

Since your overload is only responsible for the allocation/deallocation part, it should call ::operator new and ::operator delete instead of ::new and ::delete.

The delete in delete myClass; is responsible for calling the destructor.

::delete p; does not call the destructor because p has type void* and therefore the expression cannot know what destructor to call. It will probably call your replaced ::operator delete to deallocate the memory, although using a void* as operand to a delete-expression is ill-formed (see edit below).

::new MyClass(); calls your replaced ::operator new to allocate memory and constructs an object in it. The pointer to this object is returned as void* to the new-expression in MyClass* myClass = new MyClass();, which will then construct another object in this memory, ending the lifetime of the previous object without calling its destructor.


Edit:

Thanks to @M.M's comment on the question, I realized that a void* as operand to ::delete is actually ill-formed. ([expr.delete]/1) However, the major compilers seem to have decided to only warn about this, not error. Before it was made ill-formed, using ::delete on a void* had already undefined behavior, see this question.

Therefore, your program is ill-formed and you don't have any guarantee that the code actually does what I described above if it still managed to compile.


As pointed out by @SanderDeDycker below his answer, you also have undefined behavior because by constructing another object in the memory that already contains a MyClass object without calling that object's destructor first you are violating [basic.life]/5 which forbids doing so if the program depends on the destructor's side effects. In this case the printf statement in the destructor has such a side effect.


Your class-specific overloads are done incorrectly. This can be seen in your output: the constructor is called twice!

In the class-specific operator new, call the global operator directly:

return ::operator new(size);

Similarly, in the class-specific operator delete, do:

::operator delete(p);

Refer to the operator new reference page for more details.