Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Once a lock on std::weak_ptr has returned nullptr, can it ever be non-null again?

Tags:

c++

c++11

If you take a lock on std::weak_ptr:

    class foo {};

    auto s = std::make_shared<foo>();

    std::weak_ptr<foo> w{ s };

    s = nullptr;

    s.reset(new foo());

    auto l = w.lock(); // try to get previous foo

    std::cout << "locked: " << (l != nullptr) << std::endl;

Output:

locked: 0

Once lock returns nullptr, is there ever a condition under which it could return non-null, or is it effectively dead?

My test program suggests once the originally allocated object's reference count is zero then no, weak_ptr will always return a nullptr.

like image 633
keith Avatar asked Jan 25 '19 13:01

keith


People also ask

What does Weak_ptr lock do?

weak_ptr::lockCreates a new std::shared_ptr that shares ownership of the managed object. If there is no managed object, i.e. *this is empty, then the returned shared_ptr also is empty.

Is Weak_ptr lock thread safe?

std::shared_ptr and std::weak_ptr are already thread-safe.

Can a shared_ptr be null?

A null shared_ptr does serve the same purpose as a raw null pointer. It might indicate the non-availability of data. However, for the most part, there is no reason for a null shared_ptr to possess a control block or a managed nullptr .

What is the use of Weak_ptr in C++?

By using a weak_ptr , you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero.


2 Answers

is there every a condition under which it could return non-null, or is it effectively dead?

Well, it's "almost" dead at that point. lock calls expired in a way equivalent to this:

expired() ? shared_ptr<T>() : shared_ptr<T>(*this)

Then, looking at the expiration condition:

Equivalent to use_count() == 0. The destructor for the managed object may not yet have been called, but this object's destruction is imminent (or may have already happened).

Either way, there's no possibility for that specific weak_ptr to be reassigned to another value.

like image 156
Bartek Banachewicz Avatar answered Oct 22 '22 20:10

Bartek Banachewicz


#include <iostream>
#include <memory>

int
main()
{
    using namespace std;
    shared_ptr<int> p(new int{3});
    weak_ptr<int> w = p;
    p = nullptr;
    auto l = w.lock();
    if (l == nullptr)
        cout << "l = nullptr\n";
    else
        cout << "l = " << *l << '\n';
    p.reset(new int{4});
    w = p;
    l = w.lock();
    if (l == nullptr)
        cout << "l = nullptr\n";
    else
        cout << "l = " << *l << '\n';
}

Portable output:

l = nullptr
l = 4

So yes, if the weak_ptr is assigned from a non-empty shared_ptr, it can become "reanimated from the dead."

Maybe that isn't what you meant. But it is what you asked.

like image 24
Howard Hinnant Avatar answered Oct 22 '22 19:10

Howard Hinnant