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.