Alex Rivera | Logout

How is it possible (if it is) to implement shared_ptr without requiring polymorphic classes to have virtual destructor?

Asked 2010-10-10T09:41:01.797
104

Mr. Lidström and I had an argument :)

Mr. Lidström's claim is that a construct shared_ptr<Base> p(new Derived); doesn't require Base to have a virtual destructor:

Armen Tsirunyan: "Really? Will the shared_ptr clean up correctly? Could you please in this case demonstrate how that effect could be implemented?"

Daniel Lidström: "The shared_ptr uses its own destructor to delete the Concrete instance. This is known as RAII within the C++ community. My advice is that you learn all you can about RAII. It will make your C++ coding so much easier when you use RAII in all situations."

Armen Tsirunyan: "I know about RAII, and I also know that eventually the shared_ptr destructor may delete the stored px when pn reaches 0. But if px had static type pointer to Base and dynamic type pointer to Derived, then unless Base has a virtual destructor, this will result in undefined behavior. Correct me if I am wrong."

Daniel Lidström: "The shared_ptr knows the static type is Concrete. It knows this since I passed it in its constructor! Seems a bit like magic, but I can assure you it is by design and extremely nice."

So, judge us. How is it possible (if it is) to implement shared_ptr without requiring polymorphic classes to have virtual destructor?

Edit
Report

2 Answers

34

When shared_ptr is created it stores a deleter object inside itself. This object is called when the shared_ptr is about to free the pointed resource. Since you know how to destroy the resource at the point of construction you can use shared_ptr even with incomplete types. Whoever created the shared_ptr has already stored a correct deleter there.

For example, you can create a custom deleter:

void DeleteDerived(Derived* d) { delete d; }
shared_ptr<Base> p(new Derived, DeleteDerived);

p will call DeleteDerived to destroy the pointed object.

This is what the shared_ptr constructor does automatically, so in practice you don't need to implement that sort of a deleter unless you free by means other than a call to delete.

answered 2010-10-10T09:47:53.997
16

Simply,

shared_ptr uses special deleter function that is created by constructor that always uses the destructor of the given object and not the destructor of Base, this is a bit of work with template meta programming, but it works.

Something like that

template<typename SomeType>
shared_ptr(SomeType *p)
{
   this->destroyer = destroyer_function<SomeType>(p);
   ...
}
answered 2010-10-10T09:46:02.953

Your Answer