Can someone explain to me why the crash here?
#include <memory>
#include <functional>
struct Teacher : std::enable_shared_from_this<Teacher> {
struct Timetable;
std::shared_ptr<Timetable> timetable;
Teacher (int n) : timetable(std::make_shared<Timetable>(*this, n)) {}
};
struct Period {
std::shared_ptr<Teacher> teacher;
Period (const std::shared_ptr<Teacher>& t) : teacher(t) {}
};
struct Teacher::Timetable {
Teacher& teacher;
std::shared_ptr<Period> homeForm;
Timetable (Teacher& t, int n) : teacher(t), // Assume something is done with n.
homeForm( std::make_shared<Period>(teacher.shared_from_this()) ) {} // Crashes.
// homeForm( std::make_shared<Period>(std::shared_ptr<Teacher>(&teacher)) ) {} // Also crashes.
};
int main() {
std::shared_ptr<Teacher> teacher = std::make_shared<Teacher>(3);
}
Isn't teacher.shared_from_this()
allowed here since std::shared_ptr<Teacher> teacher
is a shared_ptr already? If not, how do I initialize homeForm
properly?
The problem is that your code calls shared_from_this
before the std::shared_ptr<Teacher>
is fully constructed. It somehow makes sense that the Teacher
sub-object has to be constructed before the smart pointer is fully constructed.
If you change the code like this,
struct Teacher : std::enable_shared_from_this<Teacher> {
struct Timetable;
std::shared_ptr<Timetable> timetable;
Teacher() {}
void init(int n) { this->timetable = std::make_shared<Timetable>(*this, n); }
};
// Everything else unchanged
int main() {
std::shared_ptr<Teacher> teacher = std::make_shared<Teacher>();
teacher->init(3);
}
it will run fine.
Note that I'm not recommending this as a refactoring. Constructors should fully initialize objects whenever possible. Looking at your code, it seems to me that you might want to consider re-structuring it somewhat more radical. Do you really need all this cross-referencing shared pointers?