C++ Smart pointers

What are pointers? A way of indirectly refer a memory location together with a hint about the type, a hint that the compiler uses to restrict operations on the memory location. They can point to compiler controlled memory (e.g. stack) or programmer controlled memory (dynamically allocated on heap/free store).
The main benefit offered by dynamically allocated memory is that they allow programmers to control the scope of a certain memory location, be it object/POD type/raw memory. In contrast, the scope of automatic or stack based objects/memory is maintained by the compiler and the scope is very clear (basically the inner most {} block).
With the benefit comes the main drawback … that it’s the programmer’s responsibility to allocate and de-allocate. And since that’s not always trivial, in C++ (which doesn’t have garbage collection), smart people have invented smart pointer.

A smart pointer is composed of a part that’s dynamically allocated (the pointer) and a part that’s on the stack which gives it the ‘smartness’. When the part on the stack goes out of scope (controlled by the compiler), it drags out of scope the dynamic part as well. Its purpose is to avoid leaking the memory pointed by the pointer in the ubiquitous scenario where the programmer doesn’t cover all the corner cases (and the corner cases increased dramatically with the introduction of exceptions in C++).

A C++ smart pointer looks something like:

class smartPtr
{
   smartPtr(pointer* ptr)
   {
     store ptr
     take ownership of the pointed memory/object
   }
   ~smartPtr()
   {
     deallocate ptr (calls destructors of objects)
   }
}

Taking the ownership of the allocated memory is the how the smart pointer operates. However, there are problems: What if two smart pointers try to get the ownership of the same allocated memory. Well, that’s bad and it should not be allowed. There are two main cases when this scenario can happen:

1. The programmer explicitly creates two smart pointers and initializes them with the same pointer
This is obviously a programming error and not much we can do about it except educating programmers and firing the ones that fail to learn.

2. The compiler creates copy of the smartPtr (via copy constructor, or operator=)
The compiler creates such copies when the programmer explicitly calls these two operations or in some cases where it needs to create implicit copies (returning by value, passing parameters by value).
In this case, the smart pointer implementer CAN do something about it. And there are 3 main things he can do:

a. Disallow copy constructor/operator= for the smart pointers
This is the safest option. However, it’s also the most limiting and users will soon shun the implementation because of that.

b. Transfer ownership to the new smart pointer from the old
As such, even if you have multiple copies, only one actually has the ownership. This work nicely when returning values from functions, as you want to transfer the ownership in that case anyway. It doesn’t work well with passing parameters to functions as the programmer needs to remember that after passing it by value, she can’t do anything else with the smart pointer. It’s also impossible to use in STL containers as STL is allowed to make copies of objects it holds in containers. Such a smart pointer will lose the ownership of the pointed memory in such operations.

An example of such approach is the std::auto_ptr part of STL.

c. Maintain a reference count
This strategy is must better as the smart pointer tracks how many pointers point to the allocated memory/object. It only deallocates when the last smart pointer goes out of scope. The only problem with this approach is when you end up with circular dependencies between reference counted objects. When there is such a circular dependency, none of the memory allocated in the circular dependency is de-allocated. These circular dependencies are not uncommon.

An example of such approach is the boost::shared_ptr part of boost.

Advertisements

Tags: , , ,

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: