Skip to content
April 12, 2009 / Abe Pralle

Smart Pointers in C++

I just programmed this up for a friend who’s wrestling with good ol’ dynamic allocation issues in C++.  It’s a “smart pointer” class that takes all the hard work out of managing dynamic memory.  You can find this kind of stuff elsewhere on the net too, but here’s my take:

smartpointer.h



#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H
//====================================================================
//  smartpointer.h
//
//  2009.04.12 by Abe.Pralle (at) gmail.com
//  This code is released to the public domain.
//====================================================================

#include <iostream>
using namespace std;

template <class ObjectType>
class SharedReference
{
  public:
    int count;
    ObjectType* object;

    SharedReference( ObjectType* object )
    {
      this->object = object;
      count = 1;
    }

    void retain() { ++count; }

    void release()
    {
      if (--count == 0)
      {
        delete object;
        delete this;
      }
    }
};

template <class ObjectType>
class Ref
{
  private:
    SharedReference<ObjectType>* ref;

  public:
    Ref()
    {
      ref = 0;
    }

    Ref( ObjectType* object )
    {
      ref = new SharedReference<ObjectType>(object);
    }

    Ref( const Ref<ObjectType>& other )
    {
      ref = 0;
      operator=(other);
    }

    ~Ref()
    {
      if (ref) ref->release();
    }

    void operator=( const Ref<ObjectType>& other )
    {
      if (other.ref) other.ref->retain();
      if (ref) ref->release();
      ref = other.ref;
    }

    void operator=( ObjectType* object )
    {
      if (ref) ref->release();
      ref = new SharedReference<ObjectType>( object );
    }

    ObjectType* operator*()
    {
      if (ref) return ref->object;
      else return (ObjectType*) NULL;
    }

    ObjectType* operator->()
    {
      if (ref) return ref->object;
      else return (ObjectType*) NULL;
    }
};

#endif // SMARTPOINTER_H

smartpointer.cpp


#include <iostream>
using namespace std;

#include "smartpointer.h"

class Fruit
{
  public:
    const char* name;

    Fruit( const char* name ) { this->name = name; }
    ~Fruit() { cout << " [deleting " << name << "]" << endl; }
};

Ref<Fruit> make_fruit();
void mess_with_ref( Ref<Fruit> fruit );

int main()
{
  Ref<Fruit> fruit = make_fruit();

  cout << "I have an " << fruit->name << endl;

  fruit = new Fruit( "grapes" );
  cout << "Now it's some " << fruit->name << endl;

  mess_with_ref( fruit );

  cout << "Still " << fruit->name << "!" << endl;

  Ref<Fruit> fruit2 = fruit;
  cout << "If I have two references to " << fruit->name << endl;
  fruit = new Fruit( "strawberries" );
  cout << "And I set one of them to some " << fruit->name << endl;
  cout << "Then I still have some " << fruit2->name << endl;

  return 0;
}

Ref<Fruit> make_fruit()
{
  Ref<Fruit> apple = new Fruit( "apple" );
  Ref<Fruit> orange = new Fruit( "orange" );
  return apple;
}

void mess_with_ref( Ref<Fruit> fruit )
{
  fruit = new Fruit( "some kind of weird pear" );

  Fruit* f = *fruit;
  cout << "Got the object pointer back to " << f->name << endl;
}

Test program output:

 [deleting orange]
I have an apple
 [deleting apple]
Now it's some grapes
Got the object pointer back to some kind of weird pear
 [deleting some kind of weird pear]
Still grapes!
If I have two references to grapes
And I set one of them to some strawberries
Then I still have some grapes
 [deleting grapes]
 [deleting strawberries]
Advertisements

3 Comments

Leave a Comment
  1. pizer / Apr 13 2009 4:33 am

    Hi!
    I think it’s fun to write such a smart pointer for educational purposes. But the shared_ptr of existing libraries (Boost, TR1) but also the future C++ standard library is a bit more flexible with respect to pointer type conversions and custom deleters. You should favor these advanced implementations over homebrewn smart pointers that are not so well-tested.

    Also: Never ever write a using directive in a header file that pulls many names into the global scope. Just say no.

    Cheers!
    P.

  2. Ty / Apr 13 2009 6:19 pm

    It will be a cold day in hell before I bring boost into a project for simple smart pointers.

  3. joeedh / Apr 14 2009 9:21 am

    Personally, if I do need to use C or C++, I’d rather manage the memory myself. Though there are plenty of situations where you need help and this sort of thing is useful.

    Joe

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

%d bloggers like this: