The Boost Smart Pointers library provides a set of classes to manage pointers. I've started using boost::shared_ptr and am very happy with the results. Let's see what it is.

shared_ptr is a simple templated class that holds a pointer to a dynamically allocated object, which is reference counted. The object it references is automatically destroyed when the last instance of the smart pointer is removed; this usually happens when it gets out of its code scope.

So the first and most useful application of this class is to remove (almost) all possible memory leaks from your code. You do not need to issue explicit calls to the delete operator any more, since the smart class destructor will do it for you. In other words: you get a cheap garbage collector in your code which requires no external functionality and which has a very small performance penalty.

Another use of it (and this is the main reason why I started using this class) is to make some interfaces (function prototypes) easier to understand. Consider the following class structure (coming from VCS Made Easy:

struct entity { ... }
struct tree : public entity { ... }
struct group : public entity {
void add_entity(entity* e);

group is an entity container, as you can guess from its name and from its add_entity method. Note that this method takes a pointer to an entity object. Now the doubt arises: does this pointer refer to a dynamically allocated object or to something else (i.e., on the stack)? That is: will the class take care to delete all objects it holds or will leave that task to the caller?

In my first implementation, the function was meant to take a dynamically allocated instance, because group's destroyer manually took care to delete all of its contents. This destructor could produce errors if the user inserted an stack object in the container, because delete could not be applicable. Thus I had to stick a big comment near the function definition warning the user.

Using smart pointers, the interface becomes clearer, and there is no possibility to make the mistakes outlined above. The prototype becomes:

void add_entity(boost::shared_ptr e);

It's now clear that the function takes a pointer to a dynamically allocated object (due to the nature of the smart pointers). Anyway, if it referred to a locally allocated object (I'm not sure if shared_ptr can do that), this could cause no problems because only the last instance deleted could cause the real object to be freed (no matter in which order the objects were destroyed). Plus we've also got ridden of group's destroyer!

Therefore, this is an easy way to make your code safer and clearer. Note that there are several other interesting smart pointers that you may want to look at, but I'll leave those to the documentation.

Go to posts index

Comments from the original Blogger-hosted post: