By kfmfe04

2011-12-01 08:47:29 8 Comments

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?


@ltjax 2011-12-01 10:38:02

The only non-owning smart-pointer in the standard library is std::weak_ptr. However, to use it, the actual owning object needs to hold the pointee in a std::shared_ptr.

I assume you used std::unique_ptr on those before. If you convert them to shared_ptr now, you'll have the benefit that your non-owning pointers can know that the owning pointer lost is reference while raw pointers can be left dangling without any chance for the non-owning component to detect this. However, shared_ptr will incur a (very?) small performance and memory overhead over unique_ptr.

Personally, I recommend using one shared_ptr and many weak_ptrs instead of one unique_ptr and many raw-pointers in the general case and use unique_ptr if you really have a performance problem!

@Nicol Bolas 2011-12-01 17:26:08

+1 to the use of weak_ptr for holding pointer references, even if there is only one owner. The nice thing about weak_ptr is that it actually checks to see if the object is gone. It gives you the power to put in some verification to see if an object was deleted. A naked pointer can't do that.

@David 2011-12-04 16:12:59

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.

@Howard Hinnant 2011-12-04 19:03:24

+1 Don't make easy things hard. Don't make simple things complicated.

@kfmfe04 2011-12-04 20:16:39

+1 your observations are consistent with my limited experience in this area - nice to get an affirmation and a clear statement of usage - ty

@abergmeier 2013-05-28 17:03:48

There seem to be very few cases, when you would use a raw pointer over a reference. Or do you seriously check whether the pointer is a nullptr before using it?

@David 2013-05-29 11:38:44

@LCIDFire No, I virtually never pass a raw pointer which optionally can be null; That's no the reason to pass by raw pointer. I pass by reference when the object is only used in the scope of the method. I pass by pointer when the method stores off the pointer (generally as a class member) beyond the scope of it's call. Obviously, you could just take the address of a reference passed to you, but I believe doing what I said above is clearer.

@Domi 2013-11-25 06:43:59

It's good advice. I'm recommending the same.

@Qix 2017-01-31 21:48:06

Plus you can always check if a shared_ptr is valid by coercing it to a bool.

@GManNickG 2011-12-01 09:42:09

Use a shared_ptr when you require multiple things own a resource (and those owning things may go in and out of scope at "random"), use a unique_ptr when a single thing owns the resource, and use a raw pointer when you just need to refer to it and not own it (and expect this referral to not last longer than the resource exists).

There is a fourth type, a sort of raw-pointer-for-shared_ptr's, called weak_ptr. You use that to refer to a shared_ptr without actually owning it; you can then check if the object is still there and use it.

Related Questions

Sponsored Content

6 Answered Questions

[SOLVED] Raw pointer lookup for sets of unique_ptrs

0 Answered Questions

Unity C++ plugin persistent std::shared_ptr

  • 2018-02-15 06:34:17
  • SatbirSingh
  • 143 View
  • 0 Score
  • 0 Answer
  • Tags:   c++ c++11 unity3d

2 Answered Questions

[SOLVED] Practical code-friendly name for non-owning smart-pointer

  • 2017-02-15 16:26:09
  • Jojje
  • 238 View
  • 1 Score
  • 2 Answer
  • Tags:   c++ pointers stl

11 Answered Questions

[SOLVED] Smart Pointers: Or who owns you baby?

4 Answered Questions

[SOLVED] C++11 Smart Pointer Semantics

1 Answered Questions

1 Answered Questions

1 Answered Questions

[SOLVED] Conversion to non-scalar type with std c++11 smart pointer

Sponsored Content