Loving std::unique_ptr

by Malte Skarupke

I am falling in love with std::unique_ptr.

It’s part of the new C++11 standard and is pretty much a smarter way of doing auto_ptr. The main difference is that you can not assign or copy it. Meaning it really is just a handle for a pointer that deletes it’s content when it gets destroyed.

Which doesn’t sound like much, but it will stop you from making so many mistakes. The benefit of it is that now you have a clear concept of who owns the content of the pointer.

Any time where you used to do

class Foo
{
    Base * member;
public:
    Foo() : member(new Derived()) {}
    ~Foo() { delete member; }
};

should just be replaced with

class Foo
{
    std::unique_ptr<Base> member;
public:
    Foo() : member(new Derived()) {}
};

The benefits of this are many:

  1. You can’t forget to delete it.
    The object now has a clear scope. This is pretty obvious, and few people make the mistake to forget to delete stuff in the destructor, but there are other times where people could potentially forget, like when assigning a new value to the pointer. In the end this is just one less bug that does occasionally happen.
  2. Noncopyable by default.
    Your class is now noncopyable. Which is the way it should be, because this forces you to think about how to implement the copy constructor and assignment operator.
    How often is this a problem? Not often in an ideal world, because it is many programmer’s habit to go to the copy constructor and assignment operator first after adding a new member. But hey, these are two less bugs that do occasionally happen.
  3. Clear ownership.
    It is now clear that this object owns that member. The member is not a pointer to something that lies somewhere else. I have the unique_ptr to it. Other people can still have a regular pointer or a reference, but it is clear that this object belongs to me and I will take care of cleaning it up.

In the end this is just a mechanism that makes it less likely for you to make mistakes. For me using unique_ptr every time that you know the scope of a pointer is now considered part of good coding, just as for example using “const” is. It isn’t required but it will save you every once in a while.

I have even started writing code like this:

switch( fileChunk.Type )
{
// ...
case MarkSkel:
{
    std::unique_ptr<Skeleton> newSkel(new Skeleton());
    newSkel->readFrom(file);
    animationController->setSkeleton(newSkel.release());
}
break;
// ...
}

This is a real piece of code. At first it seems pretty stupid to use a unique_ptr for a pointer that only lives for two more lines, but this makes working with this code easier. I can quickly think of two benefits of using unique_ptr here:

  1. Lifetime of the object is clear.
    I release the unique_ptr just before calling setSkeleton. This means that I expect setSkeleton to now take ownership of this object.
    Let’s say we have a memory leak in the animation code, then writing all code like this makes finding it much easier. All we have to do is look at the pieces of code where one function expects another function to take ownership. If the other function doesn’t create a unique_ptr or a shared_ptr with the argument it has received, then we very likely have found the source of the leak.
  2. Code is more robust against modification.
    I can now more easily modify this code. I can comment out any line and not have a memory leak. I can pull the lines of code apart and perform twenty operations inbetween and I don’t have to worry that I might forget to clean up at the end. I can move the code to another location without the worry that I might forget to also copy the cleanup code. I can start throwing exceptions or do other things that break the flow of execution. (like using continue, break or return early)
    In one sentence: It is now less likely that this particular piece of code will cause me bugs in the future, when I will inevitably change things in here.

So yeah, I’m falling in love with unique_ptr. I am slightly worried that I’m overusing it at the moment, and here is one final example that might be overusing:

I have recently had to work with the SDK for the FBX file format. The authors of that library have decided that all objects must be created using a static member function called Create() and destroyed using a member function called Destroy().

One of the first things I did was implement this:

template<typename T>
class FbxPointer : public std::unique_ptr<T, void (*)(T *)>
{
public:
    FbxPointer(T * ptr = nullptr)
        : unique_ptr(ptr, &FbxPointer::destroy)
    { }
    FbxPointer(FbxPointer && other)
        : unique_ptr(std::move(other))
    { }
    FbxPointer & operator=(FbxPointer && other)
    {
        unique_ptr::operator=(std::move(other));
        return *this;
    }
private:
    static void destroy(T * ptr)
    {
        if (ptr) ptr->Destroy();
    }
};

All this is, is a class that calls Destroy for me. Seems like a lot of code for something so simple. But well I like the benefits of unique_ptr so much that I simply don’t want to miss it when using a new library. A bit overzealous? Maybe, but this will have been worth it even if this only saves me from one single bug where I forgot to clean up something or where multiple things accidentally have a pointer to the same thing even though they shouldn’t. I’m even thinking of implementing my own version of make_shared for this pointer, so that I don’t even have to call the Create() method.

Finally you can use unique_ptr with the pimpl idiom:

// Foo.h:
class Foo
{
    struct HiddenInternals; // internals that depend on a library
                            // which I don't want in the .h file
    std::unique_ptr<HiddenInternals>
public:
    Foo();
    ~Foo();
};

// Foo.cpp:
struct Foo::HiddenInternals
{
    // ...
};

The only thing that is required for this example to work is, that the constructor and destructor of Foo are not default. They can even be empty as long as they are declared in the .cpp file where the definition of HiddenInternals is visible.

For some reason I expected that hiding the implementation details of a class would not be possible with unique_ptr. But if you think about it this should compile without a problem as long as the internal struct is visible when the destructor gets called. And it does.

So: Start using unique_ptr as much as you can. If you think you’re overusing it, you’re probably doing it right. Like const, you should start considering it a part of good coding practice.