C++ – When NOT to use virtual destructors

cvirtual-functions

I believed I searched many times about virtual destructors, most mention the purpose of virtual destructors, and why you need virtual destructors. Also I think in most cases destructors need to be virtual.

Then the question is: Why doesn't c++ set all destructors virtual by default? or in other questions:

When do I NOT need to use virtual destructors?

In which case I should NOT use virtual destructors?

What is the cost of using virtual destructors if I use it even if it is not needed?

Best Answer

If you add a virtual destructor to a class:

  • in most (all?) current C++ implementations, every object instance of that class needs to store a pointer to the virtual dispatch table for the runtime type, and that virtual dispatch table itself added to the executable image

  • the address of the virtual dispatch table is not necessarily valid across processes, which can prevent safely sharing such objects in shared memory

  • have an embedded virtual pointer frustrates creating a class with memory layout matching some known input or output format (for example, so a Price_Tick* could be aimed directly at suitably aligned memory in an incoming UDP packet and used to parse/access or alter the data, or placement-newing such a class to write data into an outgoing packet)

  • the destructor calls themselves may - under certain conditions - have to be dispatched virtually and therefore out-of-line, whereas non-virtual destructors might be inlining or optimised away if trivial or irrelevant to the caller

The "not designed to be inherited from" argument wouldn't be a practical reason for not always having a virtual destructor if it weren't also worse in a practical way as explained above; but given it is worse that's a major criterion for when to pay the cost: default to having a virtual destructor if your class is meant to be used as a base class. That's not always necessary, but it ensures the classes in the heirarchy can be used more freely without accidental undefined behaviour if a derived class destructor is invoked using a base class pointer or reference.

"in most case destructors need to be virtual"

Not so... many classes have no such need. There are so many examples of where it's unnecessary it feels silly to enumerate them, but just look through your Standard Library or say boost and you'll see there's a large majority of classes that don't have virtual destructors. In boost 1.53 I count 72 virtual destructors out of 494.