C++11: Replace all non-owning raw pointers with std::shared_ptr()?

kfmfe04 picture kfmfe04 · Dec 1, 2011 · Viewed 18k times · Source

With the advent of std::unique_ptr, the blemished std::auto_ptr can finally be put to rest. So for the last several days, I have been changing my code to use smart pointers and to eliminate all delete from my code.

Although valgrind says my code is memory-clean, the semantic richness of smart pointers will make for cleaner and easier-to-understand code.

In most of the code, the translation is simple: use std::unique_ptr for in place of the raw pointers held by the owning objects, throw out delete, and carefully sprinkle get(), reset() and move() calls, as needed, to interface well with the rest of the code.

I am at the point where I am translating non-owning raw pointers to smart pointers now.

Since I was careful with the lifetimes of my objects (I ensure my modules only depend in one direction), valgrind tells me that I don't have any uninitialized reads, dangling pointers, or leaks. So, technically, I could just leave those non-owning raw pointers alone now.

However, one option is to change those non-owning raw pointers to std::shared_ptr because I know they are acyclic. Or, would it be better to leave them as raw pointers?

I need some advice from veteran users of smart pointers as to what rules of thumb you use to decide whether to keep non-owning raw pointers as-is, or to translate them into std::shared_ptr, keeping in mind that I constantly unit-test and valgrind my code.

EDIT: I might be misunderstanding the use of std::shared_ptr - can they be used in conjunction with std::unique_ptr, or is it the case that if I use std::shared_ptr, all handles should also be std::shared_ptr?

Answer

David picture David · Dec 4, 2011

Personally, this is how I (more or less) do it:

  • unique_ptrs are for sole ownership
  • raw pointers mean whoever gave me the raw pointer guarantees the lifetime of that object to match or exceed my lifetime.
  • shared_ptrs are for shared ownership
  • weak_ptrs are for when a system wants to check if the object still exists before using it. This is rare in my code since I find it cleaner to have a system guarantee the lifetime of anything it passes it's subsystems (in which case I use a raw pointer)

By far I use more unique_ptrs than shared_ptrs, and more raw pointers than weak pointers.