yapkm01
yapkm01

Reputation: 3775

C++ why need weak_ptr when we have shared_ptr use_count()?

Asking a dumb question. From what I understand one usage of weak_ptr is to check the count status of shared pointer on an object. Couldn't we just use the shared_ptr use_count() to get this info. If so why need weak_ptr?

As an example:

#include <memory>
#include <cassert>
using namespace std;

int main() {

    shared_ptr<int> a(new int(10));
    weak_ptr<int> wa(a);
    a.reset();
    assert(a.use_count() == 0); // clause 1 - good. indicate no binding objects
    assert(wa.lock() == nullptr); // clause 2 - good. same as above

    return 0;

}

Clause 1 & 2 produces identical results.
So why need weak_ptr (putting aside thread safety) to test for null binding objects when shared_ptr.use_count() can do the job?

Thanks.

Upvotes: 0

Views: 168

Answers (2)

JaMiT
JaMiT

Reputation: 16803

From what I understand one usage of weak_ptr is to check the count status of shared pointer on an object.

This is not a common use, in part because it is gratuitously complicated. If you have a shared_ptr and want to know if its use count is zero, you can get that information directly from the shared_ptr. There is no need to construct a weak_ptr for this task.

In fact, constructing a weak_ptr is typically pointless unless it has a different lifetime than the shared_ptr from which it is constructed. It's only when the source shared_ptr is not accessible that a weak_ptr has value. At which point, there is no question that the weak_ptr is needed.

So why need weak_ptr (putting aside thread safety) to test for null binding objects when shared_ptr.use_count() can do the job?

If you have a shared_ptr available, you do not need a weak_ptr to the same object. But do not use use_count to check the status of the pointer (or for anything other than debugging). Instead, use get or just use the shared_ptr in a boolean context. That is, given shared_ptr<int> a; one can test the "count status" simply by if (a), where truth means a manages an object / has a use count greater than zero, and falsity means a does not manage an object / has a use count of zero. (Some people prefer if (a != nullptr) for greater clarity.)

To put it in terms of your example code:

#include <memory>
#include <cassert>

int main() {
    std::shared_ptr<int> a(new int(10));
    a.reset();
    assert(!a); // clause 3 - good. indicate no binding objects
}

To be pedantic, there is a pathological case where a shared pointer could be non-null yet not manage an object. However, this results from (mis-)use of the aliasing constructor, not reset(). The aliasing constructor is an advanced topic, so let's skip it here.

Upvotes: -1

Joshua
Joshua

Reputation: 43188

No, no we cannot.

The idea of weak_ptr is we want to have a reference to something but not keep it alive ourselves; that is when the strong references go away, so does the object; and when we resolve the weak pointer we get a null back.

One example of a weak_ptr might be in a binary tree; suppose every node needs a reference to its parent node. If you used shared_ptr to reference the parent node you would have a cycle which results in a memory leak, but the weak_ptr on the parent node doesn't.

There are other uses for weak pointers where you can have a reference to some large object from a place unrelated to its actual lifetime; but constructing a small easy to understand example is not trivial.

Upvotes: 1

Related Questions