2016-03-06 137 views
2

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

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

是不是teacher.shared_from_this()这里不允许因为std::shared_ptr<Teacher> teacher是一个shared_ptr了吗?如果不是,我该如何正确初始化homeForm

回答

2

问题是您的代码在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); 
} 

它将会运行得很好。

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

+1

基本上,它是在'enable_shared_from_this'基础中设置'weak_ptr'的'shared_ptr'构造函数。所以你需要构建整个'shared_ptr '而不仅仅是'Teacher'。 – Barry

+0

谢谢。但在我的实际程序中,教师构造函数具有需要传递给Teacher :: Timetable构造函数的参数。这意味着init需要接收这些参数。我已经更新了我的问题。在main()中复制这些参数是唯一的方法吗?或者将这些参数存储在'Teacher'中,然后将它们传递给'init',尽管它们只是暂时的? – prestokeys

+0

@prestokeys我不明白你为什么必须将它们传递给构造函数。但我会重复一遍,我不*广告使用'init'函数或这种编码风格。 – 5gon12eder