C++ Destructor Definition
- One
- Special
- Deterministic –> called at well defined times
- Automatic –> object out of scope or delete
- Symmetric –> constructor fits
- Member –> part of a class
- Function
- With
- A special name (~)
- No parameters
- No return type
- Designed to
- Give last rites
- Before object death
C# uses finalizer different (called by GC) non-deterministic, same in Java
When destructors are called
- Global or static object, called when terminates
- Arrays destructed in reverse way
- STL container , unspecified order
- delete operator
- out of scope
- temp objects
- exception thrown (stack unwinding)
- explicitly
- exit()
- abort (does not call destructor)
Order of destruction
- Rule of thumb: Reverse order of construction
- Specifically
- Destructor body
- Data members in reverse order of declaration
- Direct non-virtual base classes in reverse order
- Virtual base classes in reverse order
Implicit Destructors
- not specified by programmer
- inline by default
- public
- recommended for struct-like POD-only objects
- for everything else, avoid implicit destructors
- better debugging
- improved perf analysis
Trivial Destructors
- Implicit
- Not virtual
- All direct base classes have trivial dtors
- All non-static members have trivial dtors
- Destructors that never do anything
Virtual Destructors
- Guarantee that derived classes get cleaned up
- Rule of thumb: if class has virtual functions, dtor should be virtual
- if delete on Base* could ever point to a Derived*
- Perf: Obj with any virtual funcs includes a vtable ptr
- Idiom exceptions: mixin classes
- Pure signals abstract class (virtual ~T() = 0{})
Partial Construction & Destruction
- Dtors are only called for fully constructed objects
- if a ctor throws, obj was not fully constructed
- obj dtor will not be called
- but fully constructed subobjects will be destroyed
- Always use RAII with ctors
- Resource Acquisition Is Initialization
Virtual Functions in Destructors
- Virtual functions are not virtual inside dtors
C++ Exception Handling
- Destructors : Exceptions :: Spock : Kirk
- Wrap any function that acquires a resource in a class where dtor releases the resource
- Never allow an exception to exit a dtor
- Best: don’t throw in dtor
- OK: wrap throwing code in a try/catch
- Good advice even if you don’t use C++EH
Multithreading
- You are responsible for protecting objects and their contents
- Sharing an object across threads
- Use shared_ptr
- or some other reference counting
- or otherwise ensure only one thread can destroy
- Protect shared memory (global counters, ref counts) in dtor
delete and Destructors
- delete p is a two-step process
Explicit Destructors
- Destructors can be called directly
- Avoid 99.9% of the time
- Very powerful for custom memory scenarios
- Examples
- w / placement new
- STL allocators
std::allocator
- Allocators enable custom STL container memory
- Two key destructive functions
shared_ptr
- Templated non-intrusive deterministically referenced-counted smart pointer
shared_ptr deleters
- Deleter : a functor called on the stored raw pointer when ref count hits zero
Performance
- Destructors are called a LOT
- they are invisible in code
- streamline common dtors
- the best dtor is empty
- inlining
- profile