Why does shared_ptr have a public reset() method

Why does boost::shared_ptr have a public reset() method? Why is this method not private? In reading the introduction for weak_ptr, it seems like its main purpose is to cover up or control this opening to boost::shared_ptr. http://www.boost.org/libs/smart_ptr/weak_ptr.htm If boost::shared_ptr didn't have this type of public access, would there be a need for the weak_ptr? I can not find any example code that would justify the requirement for the weak_ptr other than the code in above link.

In article <008001c6260b$a0b7be90$0f00a8c0@david>, "David Maisonave" <boost@axter.com> wrote:
I can not find any example code that would justify the requirement for the weak_ptr other than the code in above link.
You need weak_ptr when you have cycles in your object graph. For example: struct C1; struct C2; struct C1 { shared_ptr<C2> p; } struct C2 { shared_ptr<C1> p; } C1* p1 = new C1(); shared_ptr<C1> c1(p1); C2* p2 = new C2(); shared_ptr<C2> c2(p2); c1.p = c2; c1.p = c1; Given this code, neither the object at p1 nor the object at p2 will ever be destroyed, because the cyclic dependency prevents refcounts from ever going to zero. If you change either shared_ptr to a weak_ptr, the code correctly disposes of both objects when both smart pointers go out of scope. Ben -- I changed my name: <http://periodic-kingdom.org/People/NameChange.php>

David Maisonave wrote:
Why does boost::shared_ptr have a public reset() method?
Why shouldn't it? Can you explain the reasoning that lead you to this question?
Why is this method not private?
It's not used internally, so there is no need to make it private. reset() is a simple shorthand for swapping your shared_ptr with a temporary default-constructed one, then destroying the temp. You can also achieve the same effect by assignment. p = shared_ptr<T>(); // same as p.reset() Don't tell me that your smart pointer doesn't support assignment. :-)
In reading the introduction for weak_ptr, it seems like its main purpose is to cover up or control this opening to boost::shared_ptr.
This example is why weak_ptr doesn't have a get() member returning a raw pointer. reset() is used for simplicity, you can also pretend that p is simply destroyed instead of being reset.
If boost::shared_ptr didn't have this type of public access, would there be a need for the weak_ptr?
Yes of course. The pointee can be destroyed without ever using reset.
I can not find any example code that would justify the requirement for the weak_ptr other than the code in above link.
It's hard to explain the usefulness of weak_ptr with one simple example. In short, weak_ptr allows you to keep an eye on a pointee without affecting its lifetime. You can periodically check whether the pointee is still alive and if so, obtain a shared_ptr to it (by using weak_ptr<>::lock). This shared_ptr would now temporarily keep the pointee alive until you are finished with it. There is no single canonical use for weak_ptr. It's a versatile tool that can be used in every situation that matches the above description. Some people use for it to break shared_ptr cycles. Others use it instead of a raw pointer to check for dangling pointers. It can be used in a video game to store the current target of the unit or the current selection. It can be used in a document editor as a 'weak' reference to a portion of the document, if this portion can disappear. And so on. The most often cited example is a cache. Imagine you having a collection of immutable objects that are expensive to create, such as images that are kept on disk. You receive a request from user code for image "test.tga" and give it a shared_ptr<image> to it. Now if you keep a weak_ptr, you'll be able to service the next request for "test.tga" without going to the disk if the first client is still using it. I believe that this last scenario is one of the reasons for adding a weak reference to Java.
participants (3)
-
Ben Artin
-
David Maisonave
-
Peter Dimov