Reimundo Heluani Reimundo Heluani - 2 months ago 11
C++ Question

Lifetime of dependent classses in C++?

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
?

Answer

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

}
Comments