Why is delete operator required for virtual destructors
Because of deleting destructors. That are functions that are actually called when you call delete obj
on an object with virtual destructors. It calls the complete object destructor (which chains base object destructors — the ones that you actually define) and then calls operator delete
. This is so that in all places where delete obj
is used, only one call needs to be emitted, and is also used to call operator delete
with the same pointer that was returned from operator new
as required by ISO C++ (although this could be done more costly via dynamic_cast
as well).
It's part of the Itanium ABI that GCC uses.
I don't think you can disable this.
In C++20 there is now a fix: P0722R3. The static void operator delete(T*, std::destroying_delete_t)
deallocation function. It essentially maps to the destroying destructor.
You can just make it not call ::operator delete
, like:
class Base {
public:
void operator delete(Base* p, std::destroying_delete_t) {
// Shouldn't ever call this function
std::terminate(); // Or whatever abort-like function you have on your platform
// The default implemenation without any overrides basically looks like:
// p->~Base(); ::operator delete(p);
// Which is why the call to `operator delete` is generated
}
virtual ~Base() {}
};
class Derived : public Base {
public:
// Calls Base::operator delete in deleting destructor, so no changes needed
~Derived() {}
};
int main() {
Derived d;
}
The deleting destructor is the one called when you do delete ptr_to_obj;
. It can only be called by delete
expressions, so if you have none in your code, this should be fine. If you do, you can replace them with ::delete ptr_to_obj;
and the deleting destructor will no longer be called (it's purpose is to call overriden operator delete
's for classes, and ::delete
will only call the global ::operator delete
)