123

I am programming with normal pointers, but I have heard about libraries like Boost that implement smart pointers. I have also seen that in Ogre3D rendering engine there is a deep use of shared pointers.

What exactly is the difference between the three, and should I stick on using just a type of them?

Mateen Ulhaq
  • 18,406
  • 13
  • 75
  • 112
tunnuz
  • 21,380
  • 29
  • 86
  • 124

5 Answers5

151

Sydius outlined the types fairly well:

  • Normal pointers are just that - they point to some thing in memory somewhere. Who owns it? Only the comments will let you know. Who frees it? Hopefully the owner at some point.
  • Smart pointers are a blanket term that cover many types; I'll assume you meant scoped pointer which uses the RAII pattern. It is a stack-allocated object that wraps a pointer; when it goes out of scope, it calls delete on the pointer it wraps. It "owns" the contained pointer in that it is in charge of deleteing it at some point. They allow you to get a raw reference to the pointer they wrap for passing to other methods, as well as releasing the pointer, allowing someone else to own it. Copying them does not make sense.
  • Shared pointers is a stack-allocated object that wraps a pointer so that you don't have to know who owns it. When the last shared pointer for an object in memory is destructed, the wrapped pointer will also be deleted.

How about when you should use them? You will either make heavy use of scoped pointers or shared pointers. How many threads are running in your application? If the answer is "potentially a lot", shared pointers can turn out to be a performance bottleneck if used everywhere. The reason being that creating/copying/destructing a shared pointer needs to be an atomic operation, and this can hinder performance if you have many threads running. However, it won't always be the case - only testing will tell you for sure.

There is an argument (that I like) against shared pointers - by using them, you are allowing programmers to ignore who owns a pointer. This can lead to tricky situations with circular references (Java will detect these, but shared pointers cannot) or general programmer laziness in a large code base.

There are two reasons to use scoped pointers. The first is for simple exception safety and cleanup operations - if you want to guarantee that an object is cleaned up no matter what in the face of exceptions, and you don't want to stack allocate that object, put it in a scoped pointer. If the operation is a success, you can feel free to transfer it over to a shared pointer, but in the meantime save the overhead with a scoped pointer.

The other case is when you want clear object ownership. Some teams prefer this, some do not. For instance, a data structure may return pointers to internal objects. Under a scoped pointer, it would return a raw pointer or reference that should be treated as a weak reference - it is an error to access that pointer after the data structure that owns it is destructed, and it is an error to delete it. Under a shared pointer, the owning object can't destruct the internal data it returned if someone still holds a handle on it - this could leave resources open for much longer than necessary, or much worse depending on the code.

hazzen
  • 16,126
  • 6
  • 39
  • 33
  • > If the operation is a success, you can feel free to transfer it over to a shared pointer, but in the meantime save the overhead with a scoped pointer. Can you please clarify this part of your answer? What do you mean by "feel free" to "transfer" the pointer? – amit May 06 '09 at 09:03
  • good answer! but it would be great to say shared pointers _are_ a type of smart pointers. That would clear out things. – Alba Mendez Aug 24 '12 at 19:17
  • can we say -- smart pointer help heap data behave like stack ?? – solti Feb 02 '13 at 17:05
  • "You will either make heavy use of scoped pointers or shared pointers" Can you clarify? Are you saying that projects typically use one over the other? – Elliot Cameron Sep 27 '14 at 01:27
34

the term "smart pointer" includes shared pointers, auto pointers, locking pointers and others. you meant to say auto pointer (more ambiguously known as "owning pointer"), not smart pointer.

Dumb pointers (T*) are never the best solution. They make you do explicit memory management, which is verbose, error prone, and sometimes nigh impossible. But more importantly, they don't signal your intent.

Auto pointers delete the pointee at destruction. For arrays, prefer encapsulations like vector and deque. For other objects, there's very rarely a need to store them on the heap - just use locals and object composition. Still the need for auto pointers arises with functions that return heap pointers -- such as factories and polymorphic returns.

Shared pointers delete the pointee when the last shared pointer to it is destroyed. This is useful when you want a no-brainer, open-ended storage scheme where expected lifetime and ownership can vary widely depending on the situation. Due to the need to keep an (atomic) counter, they're a bit slower than auto pointers. Some say half in jest that shared pointers are for people who can't design systems -- judge for yourself.

For an essential counterpart to shared pointers, look up weak pointers too.

  • 6
    Although "never" isn't entirely accurate. If you're implementing a smart pointer you need to use raw pointers. Outside of that special case you're much better off using the smart versions. – Max Lybbert Jan 06 '09 at 18:32
  • 1
    hopefully thats obvious to anyone reading the text –  Jan 06 '09 at 18:33
  • 1
    ... And it's rare (lim rare -> never) that implementing a smart pointer is the best solution. Generally, you should use an existing implementation, or port one if one doesn't exist for your platform. – Aaron Jan 06 '09 at 23:27
  • even with smart pointers, theres still many cases were you need raw pointers. Namely, when they have no ownership whatsoever. – Mooing Duck Jan 04 '12 at 16:22
  • 2
    @MooingDuck **What!?** a pointer with no owner?! If anyone owns it, **who does the memory management**? – Alba Mendez Aug 24 '12 at 19:20
  • 1
    @jmendeth: no, the pointer has an owner, but the pointer has no ownership of the object it points at. Namely, a pointer at another object's data. The _other object_ does the memory management. – Mooing Duck Aug 24 '12 at 19:30
  • I agree that "never" is not accurate. For example, when it comes to real time contexts (games, heavy duty tools, etc.), performance is at a premium. I'm looking for a way to document non ownership, and ideally I'd use a weak_ptr, but don't want the overhead of shared_ptr's allocations or thread synchronization (i.e. I'd have to access my objects via shared_ptr elsewhere in the code.) Nothing is for free. – topspin Mar 09 '18 at 19:13
  • BTW, this pointer type had been considered for inclusion in the std::library: http://en.cppreference.com/w/cpp/experimental/observer_ptr – topspin Mar 09 '18 at 19:29
21

Smart pointers will clean themselves up after they go out of scope (thereby removing fear of most memory leaks). Shared pointers are smart pointers that keep a count of how many instances of the pointer exist, and only clean up the memory when the count reaches zero. In general, only use shared pointers (but be sure to use the correct kind--there is a different one for arrays). They have a lot to do with RAII.

Sydius
  • 12,112
  • 16
  • 54
  • 74
  • Are smart and shared pointers included in the core C++ distribution? – tunnuz Jan 06 '09 at 18:05
  • No but they will be in the next C+ version C++1x under their boost names. –  Jan 06 '09 at 18:07
  • 8
    The time has come :) Now there are several types of smart pointers included into C++11 standard: `unique_ptr`, `shared_ptr`, `weak_ptr`. – nickolay Jan 05 '12 at 08:38
10

To avoid memory leaks you may use smart pointers whenever you can. There are basically 2 different types of smart pointers in C++

  • Reference counted (e.g. boost::shared_ptr / std::tr1:shared_ptr)
  • non reference counted (e.g. boost::scoped_ptr / std::auto_ptr)

The main difference is that reference counted smart pointers can be copied (and used in std:: containers) while scoped_ptr cannot. Non reference counted pointers have almost no overhead or no overhead at all. Reference counting always introduces some kind of overhead.

(I suggest to avoid auto_ptr, it has some serious flaws if used incorrectly)

d0k
  • 2,565
  • 18
  • 16
5

To add a small bit to Sydius' answer, smart pointers will often provide a more stable solution by catching many easy to make errors. Raw pointers will have some perfromance advantages and can be more flexible in certain circumstances. You may also be forced to use raw pointers when linking into certain 3rd party libraries.

SmacL
  • 21,621
  • 10
  • 89
  • 143