Search code examples
c++11weak-ptrmake-shared

std::weak_ptr assignment with std::make_shared


I stumbled upon this behaviour when using std::weak_ptr and std::make_shared and I found it a little weird. I am using C++11.

#include <iostream>
#include <memory>

int main()
{
  std::weak_ptr<int> weak;

  std::shared_ptr<int> shared {std::make_shared<int>(42)};
  weak = shared;
  std::cout << "Meaning of life: " << *weak.lock() << std::endl;

  weak = std::make_shared<int>(23);
  std::cout << "Meaning of life: " << *weak.lock() << std::endl;

  return 0;
}

The first std::cout prints fine, the second gives me a segfault. I tried looking at the pages of std::weak_ptr and std::shared_ptr on cppreference but I still don't understand why this happens. Having to create a temporary object feels cumbersome to me, is this something that has been addressed in C++14 or is there something I am failing to see?

Thanks!


Solution

  • The weak_ptr can only be dereferenced after locking if a shared_ptr object still exists that's pointing to the same underlying object.

    In your first part

    std::shared_ptr<int> shared {std::make_shared<int>(42)};
    weak = shared;
    std::cout << "Meaning of life: " << *weak.lock() << std::endl;
    

    this is indeed the case. In the second part

    weak = std::make_shared<int>(23);
    std::cout << "Meaning of life: " << *weak.lock() << std::endl;
    

    it is not the case, as the shared_ptr was a temporary object.

    What you've encountered here is exactly what weak_ptr was built for - that it be valid only as long as some other shared_ptr points to the same underlying object. That is its purpose:

    std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr... If the original std::shared_ptr is destroyed at this time, the object's lifetime is extended until the temporary std::shared_ptr is destroyed as well.