Smart Pointers

Smart pointers are like C pointers but with extended funcionality. Excellent information are provided in [1] and [2]. Here I’ll focus on Boost Implementation of smart pointers [3].

First, STL already provides a smart pointer, called auto_ptr. This smart pointer deletes itself whenever it goes out of scope. Furthermore, it overloads the assignment operator (=) to maintain single ownership. See the example below, extracted from [4]:

int main(int argc, char **argv)
    int *i = new int;
    auto_ptr<int> x(i);
    auto_ptr<int> y;

    y = x;

    cout << x.get() << endl; // Print NULL
    cout << y.get() << endl; // Print non-NULL address i
    return 0;

Here, when we “copy” the address in x to y, x looses the reference and points to NULL.

Boost Library

I’ll briefly describe each class of smart pointers available in boost library. As I was researching about them, I found a comprehensive and very well detailed tutorial [5].

There are six classes:

  • scoped_ptr
  • shared_ptr
  • weak_ptr
  • intrusive_ptr
  • scoped_array
  • shared_array

The scoped_ptr is almost the same as auto_ptr, except we are not allowed to copy. But still, it deletes the object pointed to after the pointer goes out of scope.

A shared_ptr allows copies and keeps track of the number of pointers referencing a given object. When this counter goes to zero, the object is then deleted. This kind of implementation may lead to cyclic reference.

/* Modified example from: */
#include <boost/shared_ptr.hpp>

/* forward declaration */
struct Square;
struct Circle;
/* sample base class */
struct Shape { 
/* class Square holds a shared pointer to class Circle */
struct Square : public Shape {
    boost::shared_ptr<Circle> circle;
/* class Circle holds a shared pointer to class Square */
struct Circle : public Shape {
    boost::shared_ptr<Square> square;
int main (){

    /* smart pointers for an instance of each class */
    boost::shared_ptr<Square> p_square(new Square); 
    boost::shared_ptr<Circle> p_circle(new Circle);

    /* circular reference */
    p_square->circle = p_circle;
    p_circle->square = p_square;
    /* make p_circle = NULL */
    /* make p_square = NULL */

    return 0;

In this scenario, we created two smart pointers for instances of each class. Let S and C be the instances of the Square class and Circle class respectively. Thus, we have each of these instances with 1 reference count. Then, when each instance points to each other, each of them now has 2 references count. Finally, when we set p_circle as NULL, C has counter 1 and S counter 2. After we set p_square as NULL, both C and S have counter 1 and none will be deleted by the end of scope, resulting in memory leak.

To avoid this, one solution presented in [5], is to use weak pointers (shared_ptr are considered strong pointers). Weak pointers mat be viewed as strong pointers that do not count reference. Thus, if we change the type of pointer in one of the classes, say the Circle, we have the following: Initially both S and C have 1 reference count. When each instance points to the other, we now have C with 2 counters and S with only one (as C pointer didn’t count reference). After p_circle is set to NULL, C and S have 1 reference counter. But when p_square is set to NULL, S counter goes to 0, forcing it to be deleted. Then, S pointer ceases pointing to C, whose counter also goes to 0.

Intrusive pointer is a flexible variation, in which the user provides the reference counting routines, in general due to performance reasons.

Finally, scoped_array and shared_array are the equivalent of scoped_ptr and shared_ptr when we’re dealing with arrays, like we do when using “new[ ]”.



Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s