Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a virtual destructor needed for your Interface, if you always store it in a shared_ptr?

Since boost::/std::shared_ptr have the advantage of type-erasing their deleter, you can do nice things like

#include <memory>

typedef std::shared_ptr<void> gc_ptr;

int main(){
  gc_ptr p1 = new int(42);
  gc_ptr p2 = new float(3.14159);
  gc_ptr p3 = new char('o');
}

And this will correctly delete all pointer thanks to the correct deleter being saved.

If you ensure that every implementation of your interface always gets created with shared_ptr<Interface> (or make_shared<Interface>), do you actually need a virtual destructor? I would declare it virtual anyways, but I just want to know, since shared_ptr will always delete the type it was initialized with (unless another custom deleter is given).

like image 394
Xeo Avatar asked Jul 09 '11 12:07

Xeo


People also ask

Should I always make destructor virtual?

Virtual base class destructors are "best practice" - you should always use them to avoid (hard to detect) memory leaks. Using them, you can be sure all destructors in the inheritance chain of your classes are beeing called (in proper order).

When would you use a virtual destructor?

Overview. A virtual destructor is used to free the space which is assigned to the object of the derived class while we are trying to delete the instances of the base class using a pointer object of the base class.

What happens when Shared_ptr goes out of scope?

All the instances point to the same object, and share access to one "control block" that increments and decrements the reference count whenever a new shared_ptr is added, goes out of scope, or is reset. When the reference count reaches zero, the control block deletes the memory resource and itself.


1 Answers

I would still follow the common rule for classes that are meant to be derived:

Provide either a public virtual destructor or a protected non-virtual destructor

The reason is that you cannot control all of the uses, and that simple rule means that the compiler will flag if you try to delete through the wrong level in the hierarchy. Consider that shared_ptr does not guarantee that it will call the appropriate destructor, only that it will call the destructor of the static type that was used as argument:

base* foo();
shared_ptr<base> p( foo() );

If base has a public non-virtual destructor and foo returns a type that derives from base, then shared_ptr will fail to call the correct destructor. If the destructor of base is virtual, everything will be fine, if it is protected, the compiler will tell you that there is an error there.

like image 134
David Rodríguez - dribeas Avatar answered Nov 13 '22 14:11

David Rodríguez - dribeas