What is the best way to implement smart pointers in C++?

dicroce picture dicroce · Feb 2, 2009 · Viewed 7.2k times · Source

I've been evaluating various smart pointer implementations (wow, there are a LOT out there) and it seems to me that most of them can be categorized into two broad classifications:

1) This category uses inheritance on the objects referenced so that they have reference counts and usually up() and down() (or their equivalents) implemented. IE, to use the smart pointer, the objects you're pointing at must inherit from some class the ref implementation provides.

2) This category uses a secondary object to hold the reference counts. For example, instead of pointing the smart pointer right at an object, it actually points at this meta data object... Who has a reference count and up() and down() implementations (and who usually provides a mechanism for the pointer to get at the actual object being pointed to, so that the smart pointer can properly implement operator ->()).

Now, 1 has the downside that it forces all of the objects you'd like to reference count to inherit from a common ancestor, and this means that you cannot use this to reference count objects that you don't have control over the source code to.

2 has the problem that since the count is stored in another object, if you ever have a situation that a pointer to an existing reference counted object is being converted into a reference, you probably have a bug (I.E., since the count is not in the actual object, there is no way for the new reference to get the count... ref to ref copy construction or assignment is fine, because they can share the count object, but if you ever have to convert from a pointer, you're totally hosed)...

Now, as I understand it, boost::shared_pointer uses mechanism 2, or something like it... That said, I can't quite make up my mind which is worse! I have only ever used mechanism 1, in production code... Does anyone have experience with both styles? Or perhaps there is another way thats better than both of these?

Answer

Aaron picture Aaron · Feb 2, 2009

"What is the best way to implement smart pointers in C++"

  1. Don't! Use an existing, well tested smart pointer, such as boost::shared_ptr or std::tr1::shared_ptr (std::unique_ptr and std::shared_ptr with C++ 11)
  2. If you have to, then remember to:
    1. use safe-bool idiom
    2. provide an operator->
    3. provide the strong exception guarantee
    4. document the exception requirements your class makes on the deleter
    5. use copy-modify-swap where possible to implement the strong exception guarantee
    6. document whether you handle multithreading correctly
    7. write extensive unit tests
    8. implement conversion-to-base in such a way that it will delete on the derived pointer type (policied smart pointers / dynamic deleter smart pointers)
    9. support getting access to raw pointer
    10. consider cost/benifit of providing weak pointers to break cycles
    11. provide appropriate casting operators for your smart pointers
    12. make your constructor templated to handle constructing base pointer from derived.

And don't forget anything I may have forgotten in the above incomplete list.