Is there a way to prevent one particular object of being destroyed while another object still exists, without explicitly making the class of the second one to know about the first?
Here is an example:
class A { /* A creates B*/ };
class B {};
int main() {
auto spA = std::make_shared<A>();
auto spB = spA->getB();
spA.reset();
spB->DoSomething();
}
After spA.reset()
, I would like to have at least one reference to the object pointed by spA
. Or, in other words: I would like to destroy the object pointed by spA
only after calling spB->DoSomething()
.
But, an important prerequisite is B
is not allowed to "know" about A
(e.g. it is not allowed to hold a pointer/reference to it).
As I understand, shared pointers provide some functionality which can help with dealing with this problem, but I am not sure which one.
EDIT:
The brief structure of A
and B
look as follows:
class A
{
public:
A()
{
m_B = B::FactoryB();
}
std::shared_ptr<B> getB()
{
return m_B;
}
private:
std::shared_ptr<B> m_B;
};
class B
{
public:
static std::shared_ptr FactoryB()
{
return std::make_shared<B>();
}
};
EDIT2 (MY SOLUTION):
So, using suggestion provided by @MSalters I was able to find a solution that works for me. In this case it was much simpler than expected, such that I only needed to adjust A::getB()
:
std::shared_ptr<B> getB()
{
std::shared<B> spBAlias(this->shared_from_this(), m_B.get());
return spBAlias;
}
Here, instead of just returning m_B
, A::getB()
creates and returns a shared pointer spBAlias
of type B
(using alias constructor), which influences the reference counting of the A
object (provided by this->shared_from_this()
). So, calling spA.reset()
in the main
decreases uses of spA
from two to one, making the call of spB->DoSomething()
possible. To use shared_from_this()
, A
needs to inherit from std::enable_shared_from_this<A>
:
class A : public std::enable_shared_from_this<A> { /* ... */ }
shared_ptr
has something called an aliasing constructor. Ashared_ptr<B>
can be created from ashared_ptr<A>
and aB*
. The destructor of thisshared_ptr<B>
will delete theA
object, not theB
.In your case, your
A
object could itself hold aunique_ptr<B>
, or even an outrightB
member.