Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it guaranteed that weak_ptr will expire when shared_ptr is reset to the same address that contains?

Is it guaranteed that weak_ptr will expire when shared_ptr is reset to the same address that contains?

#include <cassert>
#include <memory>

int main()
{
    int* i = new int(0);
    std::shared_ptr<int> si( i );
    std::weak_ptr<int> wi = si;

    si.reset( i );

    assert( wi.expired() ); // wi.expired() == true (GCC 4.7)
}

Or is this the case when the value of wi.expired() is not defined?

EDIT:

I now modify the question little bit:

Is it guaranteed that weak_ptr will expire when shared_ptr is reset to the same address, which contained a shared_ptr when it was initialized weak_ptr?

#include <cassert>
#include <memory>

int main()
{
    int* i = new int(0);
    std::shared_ptr<int> si( i );
    std::weak_ptr<int> wi = si;

    si.reset();

    int* j = new int(0); 
    // Suppose that new returns the same address that contains variable i :  
    assert(j == i); 

    si.reset( j );

    assert( wi.expired() ); // wi.expired() == true (GCC 4.7)
}
like image 544
user3123061 Avatar asked Jul 17 '14 13:07

user3123061


1 Answers

On one side, it actually should. On the other side it's not correct to assign the same pointer to two different shared pointers (si-before-reset and si-after-reset). In fact, invoking si.reset(i) it happens that:

  • the ref-count of si drops to 0
  • delete i is invoked
  • the reborn si points to i again.

so the newly assigned i after reset will point to not allocated memory, and wi is correctly expired (and will give origin to a segfault when si is gone, eventually, trying to delete i again).

Good practice is to never reference to the naked pointer after it has been assigned to a shared_ptr.

ANSWER AFTER EDIT:

The same applies there too: the fact that the pointer is the same has nothing to do with shared_ptr and its internal ref-count. This is maybe clearer with an "evil" example. This is wrong:

  int *i = new int;

  std::shared_ptr<int> si1(i);
  std::shared_ptr<int> si2(i); // deleting twice i on destruction of si2 - boom!
  std::weak_ptr<int> wi1 = si1;

  si1.reset();
  assert (wi1.expired());      // true

this is similar (really the same) of your first example: si1 and si2 are two distinct shared_ptr's (they were si-before-reset and si-after-reset). The fact that si1 and si2 (wrongly) point to the same memory has nothing to do with the life of the shared_ptr's and of the connected weak_ptr's.

The absolute value of the i pointer is not used to determine the ref-count. For both the shared_ptr's and the weak_ptr's. So yes, it is guaranteed!

In fact, when you need the shared_ptr of an object from inside its class, you need enable_shared_from_this - If you were using shared_ptr(this) instead of shared_from_this() you were getting different shared_ptr's every time - destroying your object as soon as the first of them had gone out of ref-counts.

like image 195
Sigi Avatar answered Sep 28 '22 02:09

Sigi