Pointing the Way Redux, Part 7: boost::optional

In the last installment of my more info then you ever wanted about which reference to use when series – that has also covered values, references, bare pointers, shared_ptr and unique_ptr – I covered the last of the smart pointers: weak_ptr. This time we’ll cap off the series with boost::optional. While it’s not part of the C++ standard (yet) it is still very useful and worth the trouble of pulling in the boost libraries (if you aren’t already using them).

boost::optional can be viewed as an alternative to unique_ptr that has the advantage of not requiring any dynamic memory allocation. For small objects that are easily copied boost::optional is a compelling alternative to unique_ptr when you need a nullable return type due to its stack based nature. The need to make a copy of the referenced object makes it less useful when returning a large object though. Also note that boost::optional won’t work with polymorphic types: if you do use it as a return value for a polymorphic type you’ll end up slicing the object down to the type that the boost::optional was declared to hold.

As the name implies, boost::optional can be used for optional function arguments but they have little to recommend them over bare pointers. They are also less flexible in the sense that it’s easy to take the address of an object in order to pass it when a bare pointer is called for. But if the function takes a boost::optional then you’ll have to copy your object into a boost::optional in order to call the function, a copy that you shouldn’t be forcing on the callers of functions that you write. If you’ve got a boost::optional and a function calls for a bare pointer then no copying is required, just a nullity check and an address-of operator application. Defining a little helper function to do this for you is not difficult:

template <typename Type_t>
auto ToPointer(const boost::optional<Type_t>& opt) -> decltype (&*opt)
{
   if (opt)
   {
      return &*opt;
   }
   else
   {
      return nullptr;
   }
}

As a member variable boost::optional makes sense for small objects that you don’t want to dynamically allocate but still want to have nullability for. When you have an object to store both unique_ptr and boost::optional use the same amount of memory. But when there is no object you only pay for a pointer with a unique_ptr while boost::optional will still take up the same amount of space as it did when there was an object (boost::optional always has a buffer that is at least as big as the objects that can be stored in it, that’s how it avoids dynamics memory allocation). Also note that, as with return type use, boost::optional cannot be used to store polymorphic objects. It will always slice the object that is stored in it down to the type of object it was declared to hold. All that being said, I still find myself using boost::optional as a member variable often. Also keep in mind that boost::optional makes no thread safety guarantees so you’ll need to protect accesses to boost::optional objects with mutexes and the like.

And that wraps things up. There are more esoteric types out there , like boost::variant, that are quite useful but they are also a bit more advanced and need for their use comes up much less often. This series has covered all the basic reference types that one would probably encounter in a modern C++ program – and it has already dragged on more than long enough – so I’m going to leave it here.

Advertisements

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: