I have a class A
that provides methods to construct instances of class B
. And B
holds a private reference to A
and provides a constructor to set this reference.
class A {
public:
B* construct_B ();
}
class B {
private:
const A& private_A;
public:
B ( const A& my_A ): private_A (my_A) { }
}
The implementation of construct_B
takes care of dynamic allocation and passing the reference to itself via this
.
How do I implement this setup in such a way that I make sure that the lifetime of A
is longer than B
so that its reference remains valid? Notice that I don't care about all the possibilities of construct_B
instead of returning a raw pointer I could return a smart pointer or similar.
One possible way of solving this could be having B
instead of holding a reference to hold a smart pointer to A
, and instead of dynamically allocating B
in construct_B
to take a static reference to B
and then set it's pointer, something like
class A :
public std::enable_shared_from_this<A> {
public:
void setup_B ( const B& my_B ) {
my_B.set_A (shared_ptr_from_this() ) ;
}
class B {
private:
const shared_ptr<A> private_A_ptr;
public:
void set_A ( const shared_ptr<A> my_A ):
private_A_ptr (my_A) { }
}
which then could be implemented by int main () { A static_A; B static_B; A.setup_B (static_B); }
Does the shared_ptr
of this last construction avoid the problem of A
being deleted before B
?
shared_ptr
is your answer. Something like this:
#include <memory>
struct A;
class B {
const std::shared_ptr<A> private_A_ptr;
public:
B(std::shared_ptr<A> parent) : private_A_ptr(std::move(parent)) {}
};
struct A :
std::enable_shared_from_this<A>
{
B make_b() {
return B(shared_from_this());
}
};
int main()
{
// this would be invalid:
//A a;
//auto b = a.make_b();
// but this is fine
auto pa = std::make_shared<A>();
auto b = pa->make_b();
// later...
pa.reset();
// A still exists because ownership was shared with b
}