views:

805

answers:

4

Hello All,

I am using boost shared pointer from considerable time in my project. Recently my fellow team mates have also started using weak pointers. I am not able to distinguish which to use when.

Apart from this, what should I do if I want to convert weak ptr to shared ptr. Does putting a lock on weak ptr to create a shared ptr affect my code in other thread?

Any help is appreaciated,

Thanks, Rahul

+10  A: 

Use weak_ptr when the objects you create contain cyclical references, i.e. shared_ptr to an object with a shared_ptr back to yourself. This is because shared_ptr cannot handle cyclical references - when both objects go out of scope, the mutual referencing means that they are not "garbage collected", so the memory is lost and you have a memory leak. Since weak_ptr does not increase the reference count, the cyclical reference problem does not occur. This also means in general that if you just want to take a pointer to something that is reference counted and do not want to increase its reference count, then use weak_ptr.

Otherwise, you can use shared_ptr.

For more information, check the Boost documentation.

blwy10
+1  A: 

Shared pointers implement reference counting, weak pointers do not affect reference counting and if you don't have shared pointers to an object, only weak pointers, the object gets deleted and the weak pointers now tell you that the object has been lost.

There are two reasons to use a weak pointer:

  1. To eliminate the cost of reference count increase / decrease; however you shouldn't do this because it is error-prone and doesn't really save much time
  2. In bookkeeping data structures, e.g. you have an index of all objects Foo that are "alive", i.e. used somewhere else, and you don't want to keep a Foo alive in the index if all the "real" uses have ended. This is the basic realistic use case for weak pointers. Of course others exist also.

So in general, my recommendation would be to use weak pointers only when you know that you want to let the referenced objects be deleted and want to detect that. In other cases use shared pointers (reference counting), or direct pointers, esp. in method local variables when you know that the objects are not going to get deleted. Also errorprone, though, but faster than shared pointers.

N.B. cyclical objects do not need weak pointers, you can use non-cooked, regular pointers instead in most properly constructed programs. Weak pointers less risky, though.

antti.huima
What's the third reason?
Trent
@Trent well actually there isn't, it was a typo---it was first two, then I edited it to "three" to accommodate the other answer's comment about cyclical structures, but I started to wonder why because that's not what weak pointers are for in garbage collected languages, and then I realized that you don't need 'em, so I erased it and added the N.B. Of course you can use 'em but they're just basically a type of assert, you don't need 'em for cyclical objects
antti.huima
Weak pointers do affect reference counting - shared_ptr implementations need to keep separate strong and weak refcounts for reasons too complex to get into for a comment. weak_ptr is to break cycles, end of story.
Terry Mahaffey
It's getting religious. But weak pointers exist also in properly garbage collected languages. The weak pointer concept is not related originally to cycles, but to detecting that the object behind has been deleted by the resource manager (e.g. reference counting, garbage collecting, etc.)
antti.huima
+13  A: 

In general and summary,

Strong pointers guarantee their own validity. Use them, for example, when:

  • You own the object being pointed at; you create it and destroy it
  • You do not have defined behavior if the object doesn't exist
  • You need to enforce that the object exists.

Weak pointers guarantee knowing their own validity. Use them, for example, when:

  • You access it, but it's not yours.
  • You have defined behavior if the object doesn't exist

Lock() on a weak pointer returns a strong pointer; this is how you access the weak pointer. If the object is no longer valid (it's been deleted, etc), then the strong pointer will be NULL, otherwise, it will point at the object. You will need to check this.

It's set up this way so that you cannot accidentally delete the object while you're using it, because you've made a temporary (local) strong pointer, and thus garunteed the object's existence while that strong pointer remains. When you're done using the object, you generally let the strong pointer fall out of scope (or reassigning it), which then allows the object to be deleted. For multithreading, treat them with same care you treat other things that don't have built-in thread safety, noting that the guarantee I mentioned above will hold when multithreading. AFAIK they don't do anything special past that.

The boost shared pointers also have garbage-collector like features, since when the last strong pointer to an object goes away or points somewhere else, the object gets deleted.

There's also the performance and circular dependencies mentioned in the other answers.

Fundamentally, I would say that the boost shared pointer library allows you to not fuck up putting together a program, but it is no substitute for taking the time to properly design your pointers, object ownerships and lifetimes. If you have such a design, you can use the library to enforce it. If you don't have such a design, you're likely to run into different problems than before.

Narfanator
A: 

You should probably not be trying to use weak pointers at all unless you are trying to implement a garbage collector, which is not a hot idea in C++ because it's too hard to keep track of everything that could go wrong closely enough.

Charles Eli Cheese