与shared_ptr一起崩溃

Crash with shared_ptr

本文关键字:一起 崩溃 ptr shared      更新时间:2023-10-16

有人可以向我解释为什么这里崩溃吗?

#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);
}

既然std::shared_ptr<Teacher> teacher已经是shared_ptr了,这里不允许teacher.shared_from_this()吗? 如果没有,如何正确初始化homeForm

问题是您的代码在完全构造std::shared_ptr<Teacher>之前调用shared_from_this。在完全构造智能指针之前,必须构造Teacher子对象,这在某种程度上是有意义的。

如果像这样更改代码,

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);
}

它会运行正常。

请注意,我不建议将其作为重构。构造函数应尽可能完全初始化对象。看看你的代码,在我看来,你可能想考虑重新构建它,有点激进。你真的需要所有这些交叉引用的共享指针吗?