简体   繁体   中英

pros and cons of smart pointers

I came to know that smart pointer is used for resource management and supports RAII.

But what are the corner cases in which smart pointer doesn't seem smart and things to be kept in mind while using it ?

Smart pointers don't help against loops in graph-like structures.

For example, object A holds a smart pointer to object B and object B - back to object A. If you release all pointers to both A and B before disconnection A from B (or B from A) both A and B will hold each other and form a happy memory leak.

Garbage collection could help against that - it could see that both object are unreachable and free them.

I would like to mention performance limitations. Smart pointers usually use atomic operations (such as InterlockedIncrement in Win32 API) for reference counting. These functions are significantly slower than plain integer arithmetic.

In most cases, this performance penalty is not a problem, just make sure you don't make too many unnecessary copies of the smart pointer object (prefer to pass the smart pointer by reference in function calls).

This is quite interesting: Smart Pointers .
It's a sample chapter from "Modern C++ Design" by Andrei Alexandrescu.

Watch out at the transitions - when assigning between raw and smart pointers. Bad smart pointers - like _com_ptr_t - make it worse by allowing implicit conversions. Most errors happen at the transition.

Watch out for cycles - as mentioned, you need weak pointers to break the cycles. However, in a complex graph that's not always easy to do.

Too much choice - most libraries offer different implementations with different advantages / drawbacks. Unfortunately, most of the time these different variants are not compatible, which becomes a probem when mixing libraries. (say, LibA uses LOKI, LibB uses boost). Having to plan ahead for enable_shared_from_this sucks, having to decide naming conventions between intrusive_ptr , shared_ptr and weak_ptr for a bunch of objects sucks.


For me, the single most e advantage of shared_ptr (or one of similar functionality) is that it is coupled to its destruction policy at creation. Both C++ and Win32 offers so many ways of getting rid of things it's not even funny. Coupling at construction time (without affecting the actual type of the pointer) means I have both policies in one place.

Beside technical limitations (already mentioned : circular dependencies), i'd say that the most important thing about smart pointers is to remember that it's still a workaround to get heap-allocated-objects deleted. Stack allocation is the best option for most cases - along with the use of references - to manage the lifetime of objects.

Here are a few things

  • There's no definite entity which destroys the object. Often it is desired to know exactly when and how an object is being destroyed
  • Circular dependencies - If they exist you'll have a memory leak. That's usually where weak_ptr come to the rescue.

The following article is a very interesting paper

Smart Pointers: Can't Live With 'Em, Can't Live Without 'Em

Raymond Chen is notoriously ambivalent about smart pointers. There are issues about when the destructor actually runs (please note, the destructor runs at a well-defined time in a well-defined order; it's just that once in a while you'll forget that it's after the last line in your function).

Also remember that "smart pointer" is a pretty big category. I include std::vector in that category ( a std::vector is essentially a smart array ).

There is a problem with reference counting in certain types of data structures that have cycles. There can also be problems with accessing smart pointers from multiple threads, concurrent access to reference counts can cause problems. There's a utility in boost called atomic.hpp that can mitigate this problem.

Many people run into problems when using smart pointers mixed with raw pointers (to the same objects). A typical example is when interacting with an API that uses raw pointers.
For example; in boost::shared_ptr there is a .get() function that returns the raw pointer. Good functionality if used with care, but many people seem to trip on it.
IMHO it's an example of a "leaky abstraction".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM