A question about boost::shared_ptr
here:
I have 3 Classes.
A
is some kind of Main class which is responsible to manage everything.
B
is a class which just has functions to do some work.
Dispatcher
is just a class which wraps around a seperate thread, which gets the work from Instaces of B
done in this thread.
So it is kinda working like this: A
has an instance of Dispatcher
. Now on occassion A
generates an instance of B
and passes it to the dispatcher.
The important part is, that B
needs to call A::callback()
when it's done. This is why B
gets a reference to A in it's constructor ( see code below )
A.hpp
class A : public boost::enable_shared_from_this<A>
{
public:
A();
void sendB();
void callback();
private:
Dispatcher m_Dispatcher;
};
B.hpp
class B
{
public:
B(boost::shared_ptr<A> ptr);
boost::shared_ptr<A> m_PointerToA;
/* Some other functions */
};
Dispatcher.hpp
class Dispatcher
{
public:
void run();
void dispatch(boost::shared_ptr<B> b);
private:
void doWork();
boost::thread m_Thread;
};
A.cpp
A::A()
{
m_Dispatcher.run();
}
void A::sendB()
{
boost::shared_ptr ptr_B;
ptr_B.reset(new B(this->shared_from_this);
m_Dispatcher.dispatch(ptr_B);
}
B.cpp
B::B(boost::shared_ptr<A> ptr) :
: m_PointerToA(ptr)
{
}
main_example.cpp
int main()
{
A instanceA;
while(true)
{
instanceA.sendB();
/* Do some other stuff */
}
return 0;
}
So my question is:
Is it reasonable to use boost::shared_ptr for this purpose?
I am not sure if the shared_ptr
is the right thing to go here. My problem is, that I don't know what happens exactly when I call the constructor from B
and pass it the this
pointer. Now according to shared_ptr
I would assume that m_PointerToA
takes ownership of A
. But this would mean that when the work in the Dispatcher
is done and my instance of B
gets deleted it would also delete the reference to m_PointerToA
which would actually mean it kills the object itself despite the fact there is an actual instance of A
in the main loop.
Update:
Added some code and updated question itself to make it more clear.
Yes, it is okay to just copy/assign a shared_ptr
, it will only increase the reference count.
In your example, shared_from_this()
will create a (here: temporary) shared_ptr
from the weak_ptr
that is hold by this
(ref count 1), so when you assign/copy-construct m_PointerToA
, the reference count will increase temporarily to 2 before the ctor returns and the temporary object will be destroyed, decreasing the reference count to 1 again (the shared_ptr is "aware" of the one instance in your B
object).
So, yes, if B is deleted, it will destroy A in this case (as the reference count drops to 0).
Your concern
This would mean if my Instance of B is deleted, it would also delete m_PointerToA which would also kill my instance of A . Of course my original instance of
A
is held elsewhere.
only shows that if you plan/need/intend to keep a pointer to the instance of A
for further usage, you should do so with a shared_ptr
as well instead of a raw pointer. If you have control of A
's interface, the easiest way would be a named constructor like this:
class A : public boost::enable_shared_from_this<A> {
public:
static boost::shared_ptr<A> create();
void initClassB();
// ....
private:
A();
A( const A & other );
A& operator=( const A & rhs );
};
boost::shared_ptr<A> A::create() {
return boost::shared_ptr<A>( new A() );
}
Then, even if your instance of B
is deleted, the instance of A
will still survive because the reference count of the shared_ptr
is still (at least) 1.