c++c++14weak-ptr

Calling `.lock()` on weak_ptr returns NULL shared_ptr


I am somewhat confused by the behaviour of the .lock() call on a weak_ptr. My understanding is that .lock() will return a shared_ptr of the relevant type if it has not expired otherwise it will be a null pointer.

From https://en.cppreference.com/w/cpp/memory/weak_ptr/lock :

A shared_ptr which shares ownership of the owned object if std::weak_ptr::expired returns false.

This is however not the outcome I am seeing. The code below is a method of the Unit class that should return a shared_ptr to the Unit's parent:

unsigned Unit::getParentId() const {
    auto parent = parent_.lock();
    return parent->getId();
}

The debugger output below shows that parent_ exists as a weak_ptr. However when I call auto parent = parent_.lock();, it returns a NULL pointer as can be seen in the last line of the debugger output.

I am obviously missing something really basic here?

this = {const Unit *} 0x16f1af010 
 id_ = {unsigned int} 234
 name_ = {std::string} "Test"
 parent_ = {std::weak_ptr<Unit>} std::__1::weak_ptr<Unit>::element_type @ 0x00006000034d00d8 strong=0 weak=2
  __ptr_ = {std::weak_ptr<Unit>::element_type *} 0x6000034d00d8 
   id_ = {unsigned int} 0
   name_ = {std::string} "Root"
   parent_ = {std::weak_ptr<Unit>} nullptr
   children_ = {std::vector<std::shared_ptr<Unit>>} size=0
 children_ = {std::vector<std::shared_ptr<Unit>>} size=0
parent = {std::shared_ptr<Unit>} nullptr
 __ptr_ = {std::shared_ptr<Unit>::element_type *} NULL

Solution

  • Weak pointer attaches only to existing shared pointers, by itself weak pointer doesn't hold or create any object pointer. In other words if you do:

    std::weak_ptr<int> wp;
    auto sp = wp.lock();
    

    then it always returns nullptr. You have to pass Existing shared pointer in constructor or through assignment (=), e.g.

    std::shared_ptr<int> sp = std::make_shared<int>();
    std::weak_ptr<int> wp(sp);
    auto spl = wp.lock(); // now spl is not null
    

    or through assignment

    std::shared_ptr<int> sp = std::make_shared<int>();
    std::weak_ptr<int> wp;
    wp = sp;
    auto spl = wp.lock(); // now spl is not null
    

    As long as all copies of shared pointer still exist then weak pointer will return non null on lock. Otherwise if no copies of shared pointer exist then weak pointer will always return null.

    In your case you don't have any copies of shared pointers hence weak pointer will alway return null on lock in such case.