I wrote a program where I make use of shared_ptr to the store the nodes of a graph. Each node has another object associated which keeps a shared_ptr to the node it belongs to. It seems like this is not the proper way to do it, as the child's shared_ptr to the parent is stuck (the use_count() doesn't increase when I create more shared_ptrs of the parent after construction).
The parent:
struct Parent : public enable_shared_from_this<Parent>
{
Child myChild;
Parent() :
myChild(shared_ptr<Parent>(this)) // can't use getptr() here -> bad_weak_ptr
{}
shared_ptr<Parent> getptr()
{
return shared_from_this();
}
};
The child:
struct Child
{
shared_ptr<Parent> ptr;
Child(shared_ptr<Parent> a) :
ptr(a)
{}
};
Test:
shared_ptr<Parent> p(new Parent);
cout << "UC of parent: " << p.use_count() << endl;
cout << "UC of child ptr: " << p->myChild.ptr.use_count() << endl;
shared_ptr<Parent> p2(p);
cout << "UC of parent: " << p2.use_count() << endl;
cout << "UC of child ptr: " << p2->myChild.ptr.use_count() << endl;
Output:
UC of parent: 1
UC of child ptr: 1
UC of parent: 2
UC of child ptr: 1 // expected 2!
I noticed that everything works as expected when I create the Parent through its normal ctor (no new) and get the shared_ptr via getptr(). Can someone elaborate on this? Am I doing something stupid?
Thanks in advance!
The problem is you created 2 different memory control blocks. One in the child by having it create a shared_pointer to the Parent object, and then by manually creating a shared_pointer using the newed
pointer instead of calling getptr()
which in turn calls shared_from_this
which re-uses the existing control block.
#include <iostream>
#include <memory>
using namespace std;
struct Parent;
struct Child
{
shared_ptr<Parent> ptr;
Child(Parent* a) :
ptr(a)
{}
};
struct Parent : public enable_shared_from_this<Parent>
{
Child myChild;
Parent() :
myChild(this)
{}
shared_ptr<Parent> getptr()
{
return shared_from_this();
}
};
int main()
{
shared_ptr<Parent> p = (new Parent)->getptr(); // <-- The mistake was not using shared_from_this here, this creating 2 unrelated use counts for the same object
cout << "UC of parent: " << p.use_count() << endl;
cout << "UC of child ptr: " << p->myChild.ptr.use_count() << endl;
shared_ptr<Parent> p2(p);
cout << "UC of parent: " << p2.use_count() << endl;
cout << "UC of child ptr: " << p2->myChild.ptr.use_count() << endl;
return 0;
}
Output on Coliru is:
g++ -std=c++14 main.cpp && ./a.out
UC of parent: 2
UC of child ptr: 2
UC of parent: 3
UC of child ptr: 3
Your first clue for this mistake should have been that after: shared_ptr<Parent> p(new Parent);
your counts were both 1 and 1, it should have been 2 since you have 2 shared pointers to 1 Parent object.
P.S: That being said, I'm not sure this is the best design for what you're trying to achieve, but that is a whole other question/debate.