Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using non-smart pointers in modern C++

Short Version:
Is there any acceptable reason for using non-smart pointers in modern C++?

Long Version:
we have a huge product that contains lot's of old C++ code and now we are trying to refactor it to the modern C++ era. Along with all the old fashioned code, there is huge amount of pointers passing around (mostly with SAL annotations to provide some sense of security) and I was wondering if we should change all of them to smart pointers or maybe leave some of them as is?
Trying to convert some of these codes, I ended up with a code that is simply arguable for over using smart pointers.

So the question is: is there such a thing as over using smart pointers?
Or in other words: is there any acceptable scenario for non-smart pointers these days?

like image 551
MBZ Avatar asked Oct 17 '13 03:10

MBZ


2 Answers

Smart pointers (unique_ptr and shared_ptr) should be OWNING pointers (i.e., responsible for destruction of the object). The bottom line of using them is that any object created by new should be shoved into a unique_ptr ASAP, to prevent memory leaks. After that, the unique_ptr should end up being moved:

  • either into a shared_ptr if ownership should be shared,
  • or into a unique_ptr if ownership is determined by a scope (of a block, or the lifetime of an object).

releases should be rare. If your code passes non-owning pointers around, these should be:

  • raw pointers if they may be null, (obtained by get)
  • references if they may not be null, (obtained by get)
  • unique_ptrs by value if the aim of the call is transferring ownership. (in which case you'll need to move them)

Factory methods should return unique_ptrs by value. (because then, if you don't assign the return value of the factory method, the object is immediately de-allocated)

And check out Ali's answer regarding links to some philosophical points of handling legacy code. (Which I totally agree on)

like image 110
Laurent LA RIZZA Avatar answered Oct 20 '22 22:10

Laurent LA RIZZA


Short Version:
Is there any acceptable reason for using non-smart pointers in modern C++?

Short answer:

Definitely, if they only serve for observation, that is, they don't own the pointee. However, try to use references instead of pointers even in this case; use pointers only if you really need to make them optional (initialize with null_ptr then reassign later, for example).

Long Version:
we have a huge product that contains lot's of old C++ code and now we are trying to refactor it to the modern C++ era. [...]

Long answer:

As I am reading these lines this answer comes to mind:

  • Advice on working with legacy code

I wish I could upvote this answer more than once. I would quote: "[...] for each re-factor we have made we can justify 'this specific change will make the actual task we are doing now easier'. Rather than 'this is now cleaner for future work'."

Long story short, don't do big refactoring unless you really need to.

So the question is: is there such a thing as over using smart pointers?

In my opinion, std::shared_ptr is overused. It is very comfortable to use, and it gives you the illusion that you don't have to think about ownership issues. But that is not the whole picture. I fully agree with Sean Parent: "a shared pointer is as good as a global variable." Shared pointers can also introduce very difficult ownership issues, etc.

On the other hand, if you need to allocate something on the heap, use a unique_ptr. You can't overuse it, if you really need heap allocation. In my experience, using unique_ptr also leads to cleaner and easier to understand code, as the ownership issues become self-explanatory.

Interesting talks from Sean Parent on how to avoid / reduce the usage of pointers are:

  • Inheritance Is The Base Class of Evil

  • Value Semantics and Concepts-based Polymorphism

Hope this helps.

like image 34
Ali Avatar answered Oct 20 '22 21:10

Ali