2016-03-06 196 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