Boost shared_ptr Part 1

If there was any one library that I could not live without, it would be Boost's shared_ptr library. Used in combination with RAII, it simply prevents resource leaks. Yes, really. And the basic usage is simple. What shared pointers do is maintain an internal reference count to the number of instances referencing a particular resource. When an instance shows the reference count go to zero it releases the resource. By far the most common usage is memory. Let's take a look at that.


 

In many cases, the shared_ptr can then be used just like a naked pointer:

  • de-reference it with *ptr
  • access members with ptr->mem
  • pass it to functions expecting a naked pointer of the same type using the get() operator

Where you need to pay more attention to shared_ptr is:

  • Casting pointers is done with static_pointer_cast, dynamic_pointer_cast and const_pointer_cast instead of static_cast, dynamic_cast and const_cast;
  • When using the shared_ptr as a deduced template parameter

When you need a naked pointer, use the T* shared_ptr::get() member function, which returns the underlying naked pointer.

Sometimes you want to reset a shared_ptr to an uninitialized state. To do so, use the reset() member function. If you find yourself using reset() a lot, consider whether the calling structure for your program is appropriate.

There is a separate header to manage array allocations via new[], but I recommend against it. Arrays are better handled in other ways, e.g. either via std::vector or boost::array.

There are other kinds of resources to manage. boost::shared_ptr can also handle those so long as:

  • The type has pointer semantics, meaning that it can be dereferenced with *, members can be accessed with ->, and that copies of the "pointer" are shallow copies.
  • There is a function or function object that accepts the type as an argument and releases it.
  • There is a second, optional construction argument which is the function or function object called for destruction.

It's more easily understood with an example.


 

That class could be used like this:

#include 
#include 
#include "ExSafeFILE.hpp"

typedef std::vector IntVec;
void writeToFile(const std::string& fileName) {
	static const size_t N=64;
	int p[N] = {1,2,4,8,16,32,64,128,256};
	ExSafeFILE fileHandle( fopen("test.txt","wb") );
	size_t elementSize = sizeof(int);
	fwrite(p,elementSize,N,fileHandle);
} // end writeToFile()

In keeping with the STL containers, boost::shared_ptr defines internal typedefs that are useful:

  • value_type - the type of the parameterizing type T in boost::shared_ptr
  • pointer - the type of T*

Note that the shared_ptr from Boost has been accepted into C++11. While both Visual Studio 2010 and g++ 4.4 have implementations of shared_ptr that I have tried, I continue to use boost::shared_ptr because I find it has better error messages and is more robust. Be careful about importing via using namespace boost; in conjunction with boost::shared_ptr and a C++11 compiler because you will get namespace collisions with std::shared_ptr.

Leave a Reply