Well, we realized that the behavior is undefined. But let's take a little trip into what really happens. I am using VS 2008.
Here is my code:
class Test { int i; public: Test() : i(3) { } ~Test() { if (!i) return; printf("%d", i); i--; Test::~Test(); } }; int _tmain(int argc, _TCHAR* argv[]) { delete new Test(); return 0; }
Let's run it and set a breakpoint inside the destructor, and let the miracle of recursion happen.
Here is the stack trace:

What is scalar deleting destructor ? This is what the compiler inserts between delete and our real code. The destructor itself is just a method, there is nothing special about it. It really does not free memory. It is released somewhere inside this scalar deleting destructor .
Go to scalar deleting destructor and look at the disassembly:
01341580 mov dword ptr [ebp-8],ecx 01341583 mov ecx,dword ptr [this] 01341586 call Test::~Test (134105Fh) 0134158B mov eax,dword ptr [ebp+8] 0134158E and eax,1 01341591 je Test::'scalar deleting destructor'+3Fh (134159Fh) 01341593 mov eax,dword ptr [this] 01341596 push eax 01341597 call operator delete (1341096h) 0134159C add esp,4
during our recursion, we were stuck at 01341586 , and the memory is actually freed only at 01341597 .
Conclusion: in VS 2008, since the destructor is just a method, and the entire memory deallocation code is entered into the middle function ( scalar deleting destructor ), it is safe to call the destructor recursively. But, nevertheless, this is not a good idea, IMO.
Edit : Good, good. The only idea of this answer was to take a look at what happens when you call the destructor recursively. But do not do this, it is not safe at all.
Andrey Jun 17 '10 at 16:28 2010-06-17 16:28
source share