Smart Pointers In C++ - c++

Say we have a base class and a derived. So:
class base {
protected:
~base(){
//...
}
// ...
};
class derived : public base {
// ...
};
And now say that we have this code using the above classes with a smart pointer class:
SmartPointer<base> bptr(new derived());
delete bptr;
I understand that it would prevent slicing of the derived object by calling the destructor of derived, but how does it know to do that? Wouldn't the reference stored in the smart pointer be that of type base*? Does it traverse some kind of hierarchy tree, cast that pointer to derived* and then call delete? Or is there some other thing that I don't know about?
The implementation is supposedly threadsafe, non-intrusive, and reference counting.
YES, the classes that you see are akin to the ones that I'm testing against. There is apparently a way to do this with THESE GIVEN classes. The main idea as to how is mentioned in my question above, but I'm not sure as to how one such an implementation would work.

First thing is that as it stands the code will not work. The destructor of base must be at the very least protected (or derived classes be friends of the base). A private destructor means that the compiler will not allow you to write the destructor for the derived classes. Now, assuming that you have a protected destructor... (Rembember, if you design a class to be extended, provide either a public virtual destructor or a protected non-virtual!)
All depends on the implementation of the SmartPointer, in particular std::shared_ptr (or the boost counterpart boost::shared_ptr) are able to manage that situation cleanly. The solution performs some sort of partial type erasure of the type for destruction purposes. Basically, the smart pointer has a templated constructor that accepts any pointer that can be assigned to a base pointer, but because it is templated it knows the concrete type. At that point it stores a synthetic deleter function that will call the appropriate destructor.
For simplicity, using std::function:
template <typename T>
void delete_deleter( void * p ) {
delete static_cast<T*>(p);
}
template <typename T>
class shared_pointer {
T * ptr;
std::function<void(void*)> deleter;
public:
template <typename U>
shared_pointer( U* p, std::function<void()> d = delete_deleter<U> )
: ptr(p), deleter(d)
{}
~shared_pointer() {
deleter( ptr ); // call the stored destructor
}
};
The code is for exhibition only, it would have to be tweaked for production (where to store the function, reference counting...), but it is enough to give you the idea: in the only function where the exact type of the object is known (when creating the smart pointer), you create a wrapper that will call the exact version of the destructor that you need (providing some short of type erasure), then just leave it around and when you need to delete the object call it instead of the delete operator.
This can also be used to manage other resources that require calling a special method instead of delete:
// exhibition only!
shared_pointer<Foo> p( Factory.create(), &Factory::release );
Again there should be quite a lot of work before making this production ready.
Dependency on std::function which is used to simplify the erasure, can be eliminated from the problem. In the simple case (only memory allocated with new and freed with delete is supported in the smart pointer), then just provide a deleter base class with a single virtual operator()(void*), and then refactor the existing delete_deleter into templated derived classes from deleter that override operator()(void*) with the current implementation. If you need to go for the general case (hold any type of resource) it is not worth the effort, just use std::function or boost::function.

Well first of all, your destructor shouldn't be private or that won't compile at all. Secondly, if you're using a "smart pointer", you probably should not be deleting the pointer by hand at all (I don't know what implementation you're using though, but this strikes as odd to me).
Anyways if you're curious how the derived class' destructor gets called when the object is deleted through a pointer to the base class, the answer is polymorphism. But you're missing virtual declaration from your destructor, right now your code would not call the derived class' destructor.
How most C++ implementations implement this is through a virtual table.

If you using any of boost smart pointers or some other which is not friend of your Base class, then this code wouldn't compile, because destructor of Base class is protected (which is same as private for other independent from Base classes).
Now let's consider that you make SmartPointer<Base> friend of Base. This case the code will work, but it wouldn't call destructor of Derived but destructor of Base, because here your Base class is not polymorphic. You should declare destrucotr of Base as virtual. In last case the correct destructor will be called when your smart pointer is deleted.

this program is invalid.
1) the dtor of base is private
2) the dtor of base is not virtual
to answer your question: you need to correct #1 and #2. then the dtor will be called using dynamic dispatch (which will invoke each dtor in reverse order of construction).
without making those corrections, the only way SmartPointer could know to call derived's dtor in this example, and in a defined manner, is if SmartPointer was overly clever (or tedious to use).

Your base class desctructor needs to be virtual to ensure that destructor of derived class is called when deleting via base pointer.
Wikipedia entry on virtual desctructors

Related

When I can be sure that I can inherit from c++ class?

Let's say that I use an external library full of various classes. When I can safely inherit from one of those classes? I know that the base class must have a virtual destructor. Is there something else I should check before using the class as the base class? Can I be sure that it is safe only if the docs state so?
If the documentation states that it is safe to derive a type, follow the documentation. If, for some reason, it behaves in a way that goes against the documentation, then this is a problem with the library and is a bug for the authors to fix or offer workarounds for, because they are not committing to the API that they guarantee in the documentation.
Any type that is not final can be derived "safely"; what matters more is how this type is handled and destroyed. If you inherit from a type that has no virtual destructor, this doesn't inherently break anything; it just prevents having the derived type's destructor get called if you destroy that from a handle to the base.
If you only ever destroy the type from a handle to the derived type, (e.g. you either hold it concretely, or never destroy it from a handle to the base), then this has no consequence.
To better explain my point, imagine the following hierarchy:
class Base {
public:
// No virtual destructor
...
};
class Derived : public Base {
public:
...
private:
std::string m_something; // some leakable object
};
The derivation of Derived from Base is completely safe to do. What matters is how it gets destroyed for whether there will be a problem. For this there are two different cases to consider: Automatic and Dynamic cases.
Automatic Objects
Automatic types ("by-value" types) are safe, regardless of whether they have static lifetime or not
auto d = Derived{ ... };
static auto sd = Derived{ ... };
At the end of their lifetime, the destructor Derived::~Derived will be called, since the type is concretely known
Dynamic Objects
Dynamic objects don't get destroyed on their own. Their resources need to be cleaned up eventually, either automatically with RAII in a smart pointer, by someone calling delete, or by someone explicitly calling ~T() and freeing the memory.
These are still safe if they are destroyed by a handle to the derived type, but will not be if they are destroyed by a handle to the base.
auto* d1 = new Derived{ ... };
auto* d2 = new Derived{ ... };
// Deleting as a pointer to Base; ~Derived won't be called because ~Base is virtual
// This would be a memory leak
delete static_cast<Base*>(d1); // bad
// Deleting as a pointer to Derived -- ~Derived will be called, this is fine
delete d2; // good
In terms of Smart Pointer types:
Shared Pointer
shared_ptr types are safe, since they always destroy objects from the concrete type -- even if they get aliased to a base class.
void accept_base(std::shared_ptr<Base> b);
auto d = std::make_shared<Derived>(...);
// still safe
accept_base(std::move(d));
Unique Pointer
unique_ptr types are not safe by default due to the default deleter deleting based on the T type of unique_ptr.
For example:
auto d = std::make_unique<Derived>(...);
auto b = std::unique_ptr<Base>{std::move(d)};
// b will be destroyed at end of scope by calling ~Base, which is not virtual!
Even with all of this said: If you're using a library that explicitly states that you are meant to derive some XYZ class, then you should still assume that this is how the class should be used. At that point, if something undesirable occurs, it will be up to the library maintainer to ensure that their code performs as documented, since it's part of their expressly stated API.
If you intend to call methods from a Base class reference or pointer, you should also check if they are declared virtual.
Apart from that I would look into the documentation of the class and whether it is declared final
You actually do not need a virtual destructor for it to be safe to inherit from a class. You only need a virtual destructor, if you want to use (and thereby destroy) the class from a pointer to its base class.
It all depends on how you intend to use the derived class.
For instance, if you just want to make a class that inherits from the given class, but you do not intend to use it in a base class pointer or reference.
Base baseObj;
Derived derivedObject; // This does not create any problems
If you want to use it from a pointer or reference (this also applies to smart pointers of course) to the base class like this:
Base* basePtr = new Base();
Base* basePtrToDerived = new Derived();
Derived* derivedPtrToDerived = new Derived();
// Do stuff here
delete basePtr;
delete basePtrToDerived; // if Base has no virtual destructor, only the destructor of Base is called
delete derivedPtrToDerived; // This will always call the destructor of Derived
you need a virtual destructor.

Destructor when derived class contains a pointer to base class object

I have written a pure virtual destructor and implemented it in the abstract base class and override it in derived classes.
However, in one of the classes I have a pointer to a base class object.
Now, should the destructor of the derived class be written this way:
virtual ~DerivedClass()
{
delete this->pointerToAnotherDerivedClassObject;
}
or will the object be deleted automatically? As the base class destructor is always called so I cannot decide whether it takes care of it or not.
EDIT: My mistake for stating it was a pointer to a base class, as it is actually a pointer for another derived class object.
However, in one of the classes I have a pointer to a base class object.
Now, should the destructor of the derived class be written this way
Since pointerToAnotherDerivedClassObject points at another object in memory, then yes, your DerivedClass destructor needs to explicitly delete that object (or wrap the raw pointer inside a smart pointer - std::auto_ptr, std::unique_ptr, or std::shared_ptr - and let it delete the object for you) ONLY IF DerivedClass is meant to own that other object. Otherwise, do not delete it if you do not own it.
#Elia Similar situation is discussed in the book of Eckel " thinking in C++ vol-2 " in design pattern chapter-10 regarding pseudo virtual constructor. The answer to your question is you do need to delete it considering you allocate it dynamically. Also don't confuse member Base* with the Base object which is part of derived due to inheritance, one is a data member (which is what you want to delete) other is due to inheritance.

Call destructor of derrived class only

Looking at the C++ language standard, is there any way to call only derived class destructor, without calling destructor of the base class?
So, for classes
class Base { public: virtual ~Base() {} };
class Derived : public Base { public: ~Derived();};
if would be possible to write code like
Base *basePtr = new Derived();
//do something with basePtr
// Now somehow destroy Derived while keeping Base - call ~Derived() only,
// line below however will call both ~Derived() and ~Base() - how it can be done?
dynamic_cast<Derived*>(basePtr)->~Derived();
So, after execution of the code above basePtr will point to Base object only, like if it was created by
Base *basePtr = new Base();
plus any modifications to the Base object caused by manipulating basePtr between calling new Derived() and destroying Derived class?
Or, is this forbidden and it is impossible to do?
No, this is not possible. The standard demands that the destruction of a Derived object destroys the whole object, including the Base subobject. Anything else would not be a destruction according to C++'s understanding of object lifetime.
Depending on what you want to achieve, consider to copy the Base out of the derived first
std::unique_ptr<Base> basePtr(new Derived());
//do something with basePtr
basePtr.swap(std::unique_ptr<Base> (new Base(*basePtr))); //splice the Base part out of the derived object
//basePtr now points to the spliced Base object.
Another approach would be to hold the additional members that derived has in a boost::optional (or just a pimpl) and reset that to get a "stripped" Derived object that still has its Base class part. This will however not affect virtual function dispatch.
As you have formulated the question, it is not possible to achieve what you are asking for. Unless you have a memory leak, the only case when explicitly calling a destructor does not lead to undefined behavior is if the object was created by placement new. Even then, calling the destructor will automatically call the destructor of every member and base class.
This is as it should be. Otherwise it would be very difficult to write a correct container class or memory manager.
The standard says that the lifetime of an object ends as soon as it enters the destructor. It does not become a base class object. It ceases to be an object, entirely. Also, if this was not the case, what would be the status of a class deriving from multiple bases after such a trick?
Ultimately, the "need" for such a functionality is a sign of bad design. I would guess your use case more likely requires composition. See if you can't solve it with a new class which holds one instance of what is currently the base class and one optional, replaceable component of (a smart pointer to) some dummy class which serves as an interface to and the new common base of your current derived classes. That way you can remove (and destruct) those sub objects without touching the base.
Destructors are called automatically in the reverse order of construction. I do not believe there is any way around this.
This is not possible to do unless your derived class has nothing to do with your base class.
Destructors are called in automatic way.Explicitly call destructor may result in undefined behavior.

C++ : CRTP destructor?

On a project, I have the following problem :
I have a very simple inheritance scheme (I need inheritance and not composition) :
class Base
-> class DerivedA
-> class DerivedB
-> class DerivedC
A, B and C derive from Base and that's all.
So now I have 2 choices :
public inheritance with virtuality
private inheritance without virtuality
For some optimization reasons (I need a lot of inlining) I don't want virtuality ... and I don't want private inheritance. I think that the only option that remains is CRTP. But the base class have like 300 functions and implementing CRTP in it will be a real pain.
So I wonder if the following solution is valid : I use CRTP only in the destructor of the base class :
template<class TCRTP> class Base
{
~Base() {delete static_cast<TCRTP*>(this);}
}
where TCRTP will be DerivedA, B or C and I do public inheritance.
Is it perfectly ok, or problematic ?
Thank you very much.
Your destructor is definitely wrong. The destructor of a class does not and must not delete the memory for the object.
What's your objection to public inheritance without virtual functions? There are (at least) a couple of ways to prevent someone accidentally deleting a derived object through a base pointer. One is to make the base destructor protected.
Another is to stuff dynamically-allocated instances of the derived class straight into a shared_ptr. This can even be a shared_ptr<Base>:
std::shared_ptr<Base> foo(new DerivedA(...));
Because shared_ptr has a template constructor that captures the type of its argument, the Base* pointer will be converted to DerivedA* in the deleter function associated with the shared_ptr, and hence deleted correctly. Nobody should ever be so daft as to try to extract a pointer out of a shared_ptr and delete it as Base*.
Of course if you have no virtual functions, then the trick is only really useful when the only difference between the derived classes is what they set up in their constructors. Otherwise you'll end up needing to downcast the Base* pointer from the shared_ptr, in which case you should have used a shared_ptr<DerivedA> to begin with.
I could see using code like inside the implementation of IUnknown::Release, but never in a destructor. The Base destructor only runs after the derived object has been destroyed, trying to delete the derived object at that point is undefined behavior. I'm pretty sure you'd get infinite recursion in that particular case.

Does delete work with pointers to base class?

Do you have to pass delete the same pointer that was returned by new, or can you pass it a pointer to one of the classes base types? For example:
class Base
{
public:
virtual ~Base();
...
};
class IFoo
{
public:
virtual ~IFoo() {}
virtual void DoSomething() = 0;
};
class Bar : public Base, public IFoo
{
public:
virtual ~Bar();
void DoSomething();
...
};
Bar * pBar = new Bar;
IFoo * pFoo = pBar;
delete pFoo;
Of course this is greatly simplified. What I really want to do is create a container full of boost::shared_ptr and pass it to some code that will remove it from the container when it is finished. This code will know nothing of the implementation of Bar or Base, and will rely on the implied delete operator in the shared_ptr destructor to do the right thing.
Can this possibly work? My intuition says no, since the pointers will not have the same address. On the other hand, a dynamic_cast<Bar*> should work, so somewhere the compiler is storing enough information to figure it out.
Thanks for the help, everybody who answered and commented. I already knew the importance of virtual destructors, as shown in my example; after seeing the answer I gave it a little thought, and realized the whole reason for a virtual destructor is this exact scenario. Thus it had to work. I was thrown by the absence of a visible means of converting the pointer back to the original. A little more thinking led me to believe there was an invisible means, and I theorized that the destructor was returning the true pointer for delete to release. Investigating the compiled code from Microsoft VC++ confirmed my suspicion when I saw this line in ~Base:
mov eax, DWORD PTR _this$[ebp]
Tracing the assembler revealed that this was the pointer being passed to the delete function. Mystery solved.
I've fixed the example to add the virtual destructor to IFoo, it was a simple oversight. Thanks again to everyone who pointed it out.
Yes, it will work, if and only if the base class destructor is virtual, which you have done for the Base base class but not for the IFoo base class. If the base class destructor is virtual, then when you call operator delete on the base class pointer, it uses dynamic dispatch to figure out how to delete the object by looking up the derived class destructor in the virtual function table.
In your case of multiple inheritance, it will only work if the base class you're deleting it through has a virtual destructor; it's ok for the other base classes to not have a virtual destructor, but only if you don't try to delete any derived objects via those other base class pointers.
This doesn't relate to your given example, but since you mentioned that you're really interested in shared_ptr's behavior when deleting its owned object, you might be interested in using shared_ptr's 'deleter'.
If the object owned by the shared_ptr needs special handling when being deleted, you can specify a 'deleter' for any particular shared_ptr<>. The deleter is not part of the type, it's an attribute of a shared_ptr<> instance, so your container of shared_ptr<> objects could have some objects with different deleters. Here's what the Boost docs say about the shared_ptr<> deleter:
Custom deallocators allow a factory
function returning a shared_ptr to
insulate the user from its memory
allocation strategy. Since the
deallocator is not part of the type,
changing the allocation strategy does
not break source or binary
compatibility, and does not require a
client recompilation. For example, a
"no-op" deallocator is useful when
returning a shared_ptr to a statically
allocated object, and other variations
allow a shared_ptr to be used as a
wrapper for another smart pointer,
easing interoperability.
It would be cleanest if you could modify IFoo to have a virtual destructor since you're planning to delete objects that are subclasses of it through an IFoo reference or pointer. But if you're stuck with an IFoo that cannot be corrected, then if you want to use shared_ptr<IFoo> in your container, but have it pointing to a Bar, you could create the shared_ptr instance with a deleter that performs a downcast to a Bar* then does the delete operation. Downcasts are considered bad form, but this technique might be something that you could use in a bind.