Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 973
dicroce Avatar asked Feb 02 '09 16:02

dicroce


People also ask

How do you implement a smart pointer?

Smart pointer in C++, can be implemented as template class, which is overloaded with * and -> operator. auto_ptr, shared_ptr, unique_ptr and weak_ptr are the forms of smart pointer can be implemented by C++ libraries.

Are there smart pointers in C?

Concept of the C++11 Smart PointersSmart pointers are class objects that behave like built-in pointers but also manage objects that you create with new so that you don't have to worry about when and whether to delete them - the smart pointers automatically delete the managed object for you at the appropriate time.

Are smart pointers on the stack or heap?

As shown in the example, a smart pointer is a class template that you declare on the stack, and initialize by using a raw pointer that points to a heap-allocated object.

Why should you use smart pointers instead of regular pointers?

Smart pointers should be preferred over 'raw' pointers. If you feel you need to use pointers (first consider if you really do) you would normally want to use a smart pointer as this can alleviate many of the problems with 'raw' pointers, mainly forgetting to delete the object and leaking memory.


2 Answers

"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.

like image 100
Aaron Avatar answered Oct 07 '22 21:10

Aaron


Just to supply a different view to the ubiquitous Boost answer (even though it is the right answer for many uses), take a look at Loki's implementation of smart pointers. For a discourse on the design philosophy, the original creator of Loki wrote the book Modern C++ Design.

like image 42
Don Wakefield Avatar answered Oct 07 '22 21:10

Don Wakefield