Reputation: 359
I am trying to have a shared_ptr to the parent node of a structure within itself. When deriving from such a data type, I want the parent pointer to be casted to the derived type.
Here is the piece of code I attempted to use.
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/make_shared.hpp>
using boost::shared_ptr;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
using boost::make_shared;
struct A
{
weak_ptr<A> parent;
int i;
virtual ~A() {}
};
struct B : virtual A
{
int j;
virtual ~B() {}
};
int main(int argc, char *argv[])
{
B a, b;
a.i = 1;
a.j = 2;
b.i = 4;
b.j = 8;
b.parent = weak_ptr<B>(make_shared<B>(a));
// ^^^
// The problem is here, not where I had
// thought it was earlier.
shared_ptr<B> pb;
if (pb = dynamic_pointer_cast<B>(b.parent.lock()))
{
// This is the code block that is intended to run
// but the control does not flow here.
std::cout << "b's parent: " << pb->i << ' '
<< pb->j << "\n";
}
else
{
std::cout << "Could not lock shared pointer or Pointer Null" << "\n";
}
return 0;
}
The output `fails' with the following message
Could not lock shared pointer or Pointer Null
Please explain the behaviour
Update:
I changed the title, after I learnt from the explanations, that it was actually misleading.
To me, The following comment from @Igor explain it best.
make_shared<B>(a)
creates a temporaryshared_ptr
, which is destroyed at the semicolon. You assign it toweak_ptr
- butweak_ptr
alone doesn't keep the object alive
Upvotes: 1
Views: 1020
Reputation: 13278
b.parent = weak_ptr<B>(make_shared<B>(a));
On this line you create a shared_ptr
which dies on the same line.
The weak_ptr
only stores a weak reference to it, so it doesn't count as a normal reference that increments the counter.
Therefore when you use the lock
method of weak_ptr
it returns an empty shared_ptr
.
Upvotes: 4
Reputation: 3950
When you call the following:
b.parent = weak_ptr<B>(make_shared<B>(a));
The pointer gets destroyed as soon as the weak pointer is assigned, since the weak pointer will not try to keep the object alive.
Rememeber, if there are no more shared_ptr's to an object the pointer will destroy the object and the pointer will become invalid. This is the idea of smart pointers.
Also you are mixing pointer and non-pointer objects, this is bad and can cause issues: Take note, the call to make_shared<B>(a)
will call the copy constructor of B
to create a new instance of class B
that is copied from a
. So it is not really the parent of b
, although you want it to be.
I suggest move completely over to smart pointers
int main()
{
shared_ptr<B> a = make_shared<B>();
shared_ptr<B> b = make_shared<B>();
a->i = 1;
a->j = 2;
b->i = 4;
b->j = 8;
b->parent = a;
shared_ptr<B> pb;
if (pb = dynamic_pointer_cast<B>(b->parent.lock())) {}
}
Upvotes: 2
Reputation: 8785
b.parent = weak_ptr<B>(make_shared<B>(a));
This line creates temporary shared pointer to copy of a
, and assigns weak pointer to it to b.parent
Then temporary shared pointer is destroyed, making b.parent
point to destroyed pointer, so any attempt to .lock()
it would fail.
Upvotes: 1