3

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!

antogilbert
  • 176
  • 2
  • 12

2 Answers2

5

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.

Caribou
  • 2,070
  • 13
  • 29
Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
4

This is due to the fact that you create a temporary shared pointer and assign it to a weak pointer right away in this line:

weak = std::make_shared<int>(23);

After the assignment operator ends, the temporary shared pointer is destructed, the reference count reaches 0 (since weak pointers do not increase the reference counter) and hence, the resource on the heap is deleted.