C++’s scoped_ptr and unique_ptr smart pointers

I got bitten again just the other day when I was modifying old code. It crashed. Yes, I added an extra delete when one is not required resulting in a double deletion. It reinforced my belief that most pointers in C++ should be smart pointers. A new C++ programmers will be caught often for memory leaks for forgetting to delete a pointer. As you get more experienced, while forgetting to delete becomes far less of a problem, double deletion becomes more rampant (Hey! It’s hard to keep track of object ownership you know? Especially when you’re rushing to modify other people’s code before deadline…)


To the rescue is Boost scoped_ptr smart pointer. There are two main reasons, in my opinion, to use scoped pointers.

Scoped pointers ease manual memory management. It holds a pointer to the object that it manage and it performs automatic deletion of the object it holds when it is deleted. The scoped_ptr object itself is a templated auto pointer, which means that it will be deleted automatically when it goes out of scope. Here is a simple, incomplete implementation of scoped_ptr:

template <typename T>
class scoped_ptr : noncopyable {
  explicit scoped_ptr(T* p = NULL) { p_ = p; }
  ~scoped_ptr() {
    if (p_ != NULL) delete p_;
  void reset(T* p = NULL) {
    if (p_) delete p_;
    p_ = p;

  // Some implementation may choose
  // to crash if p_ is NULL for the
  // following 3 operators.
  T& operator*() const { return *p_; }
  T* operator->() const { return p_; }
  T* get() const { return p_; }
  T* p_;

Let’s analyze the class. It extends Boost’s noncopyable interface (some would prefer to use macro for this), which implies that a scoped_ptr object may not be copied or assigned to another scoped_ptr. It induces a strict ownership of the owned pointer. As you see above, the destructor of scoped_ptr simply delete the held pointer, similarly with reset(T*) method.

This brings us to a second, more important point. scoped_ptr enforces a strict ownership of an object. In another word, it forces us programmers to think and then rethink about the ownership of an object. Many times, the problem with C++ developers are not forgetting to delete. It is not knowing who exactly owns an object. For example, let’s check out the following really simple class definition:

class ConfusedClass {
  ConfusedClass() {}
  ~ConfusedClass() {}
  void DoSomething() {
     a_ = b_.PerformSomething();
  AnotherClass* GetA() { return a_; }
  AnotherClass* a_;
  YetAnotherClass b_;

In a world without scoped_ptr, this class can be really confusing. Who owns the object held by a_? Is it b_? Is it ConfusedClass? Or is it the class who calls GetA? The last option looks unlikely here. But it’s pretty hard to differentiate between the first two cases! A subsequent reader of the class definition would probably need to dig YetAnotherClass to determines that information. (Note also that the destructor is empty, it can be that b_ holds the object held by a_, or… it can be a bug—forgetting to delete a_!)

With scoped_ptr, when we write ConfusedClass, we should be thinking about the ownership of the object held by a_. And if we think this class should owns it, we should use scoped_ptr<AnotherClass> a_ instead! That way, subsequent reader of the class definition knows for sure that the object is owned by ConfusedClass (or shall we call it SmartClass now).

As a bonus, code with multiple exit path will be easily managed with scoped_ptr (instead of hunting each exit path and making sure all the pointers that should be deleted are deleted). Imagine how troublesome it is to manage a method with a throw for example. (I remembered writing a Java code where I’ve had to always have 3 if blocks in the finally part of a try-catch-finally, to actually check for null and close a ResultSet, a PreparedStatement, and an SqlConnection. In C++, I’ll simply write a wrapper similar to scoped_ptr to perform the closing.)


C++0x expands the smart pointer repertoire even more with unique_ptr (Committee Draft §20.8.12). This smart pointer has a strict ownership as with scoped pointer. However, it is MoveConstructible and MoveAssignable (as described by the CD). What those jargons mean is that a unique_ptr s can be constructed with parameter of another unique_ptr u with a corresponding ownership transfer of the held object from u to s (MoveConstructible) and a unique_ptr u can be assigned to another unique_ptr s with ownership of the owned object transferred from u to s (MoveAssignable).

This pointer adds a little extra value to scoped pointer version. That is, you can transfer ownership (there is no release method in scoped pointer, while unique_ptr has not just a move constructor and move assignment, but also an explicit release method). This is basically a better version of std::auto_ptr (I’ve heard talk of making auto pointer deprecated).

To effectively used smart pointer, use the correct smart pointer for each of your needs. If you need a strict ownership semantics without any trasnfer, use scoped_ptr. If you need ability to transfer ownership in addition to that, use unique_ptr (or std::auto_ptr). Even better, make such rules part of your software/company’s style guide. Future maintainers will thank you when he can easily see an orderly semantics in the chaos.


There is another smart pointer introduced in C++0x. The name is shared_ptr (CD § This pointer is basically a referenced-counting smart pointers that implements shared ownership of the held object. When the last shared_ptr holding the particular object is destructed, the object is deleted too. Now, I won’t delve too much into this smart pointer because I believe in strict ownership as opposed to shared one. There should be a very, very rare situation where it demands shared ownership of an object. In a good software design, only one object should owned a particular object.

Now there is one place where shared_ptr is very, very useful: the STL containers. When you insert or retrieved a member into an STL containers, a copy of the object is made. For performance reason, keeping a pointer in the containers make lots of sense (especially when copying is expensive). As with any pointer usage, it becomes very hard to keep track of these objects. Hence the usage of shared_ptr. Copying a shared pointer is cheap. Additionally, there’s no risk of forgetting to delete a pointer within an STL containers. (Keep in mind that shared_ptr is usually twice as big as a normal pointer as it needs to keep another pointer to the reference counter.)

Example usage:

vector<shared_ptr<ClassA> > vector_of_a;
hash_map<int, shared_ptr<ClassA> > map_of_int_to_a;
Share this on:
  • Print
  • Facebook
  • Twitter
  • Digg
  • del.icio.us
  • Google Bookmarks
  • Blogplay
  • StumbleUpon

Tags: , ,

2 Responses to “C++’s scoped_ptr and unique_ptr smart pointers”

  1. Danny77uk Says:

    Good article!

    “There should be a very, very rare situation where it demands shared ownership of an object. In a good software design, only one object should owned a particular object.”

    Actually there are many cases where shared ownership is vital – the command pattern upon which most Undo systems is based relies on the command objects sharing ownership of their pointers for example. You must also often reference the same object amongst many and you must use shared pointers for that (or use .get() and return a bald pointer but then what’s the point in using smart pointers?)

  2. shards Says:

    You’re perfectly right that there are cases where shared ownership is vital. However, many times shared ownership is really not required with a change of design, most of the time for the better. I guess what I was trying to say is that whenever a shared ownership somehow becomes needed, we should try to determine whether it is really needed.

    In your second case, for example. I rarely saw two (or more classes) really needing an actual ownership of the same object, i.e. as a member of the class. Most of the time, 1 class (I really mean object) is the owner of the pointer, and the other object only needs it in a single method or two, and hence not needing to actually “own” the pointer. In this case, I’d pass a naked pointer that clearly indicates that the object receiving the naked pointer is not owning the pointer (but this is my coding convention, yours might vary). Here I make sure that the naked pointer is never stored as a member of any other object (or a callback).

    Again, I’m not claiming this to be universal, there are indeed cases where shared ownership is needed.

    (And thanks! I didn’t think the article was good. I was just hoping that it’d help beginners. I have had some good helps when I started.)

Leave a Reply