《C++標(biāo)準(zhǔn)庫,2nd》用father/mother/kids的例子揭示了shared_ptr循環(huán)引用所導(dǎo)致的析構(gòu)失敗的問題妙啃,見5.2.2档泽。這最多造成memory leak,更致命的是造成app崩潰彬祖。如我所遇:
struct displayElementPts
{
static std::shared_ptr< displayElementPts> instance(){...}
void clear(){...}
}
class dialog{
static std::shared_ptr< dialog > instance(){...}
virtual void closeEvent(...){
auto dis = displayElementPts::instance();
dis->clear();
}
}
在dialog關(guān)閉的時(shí)候茁瘦,會(huì)調(diào)用displayElementPts。
一般這是無害的储笑。但退出app的時(shí)候甜熔,對(duì)話框會(huì)調(diào)用closeEvent ,問題就在這里突倍,如果這個(gè)對(duì)話框從來就沒實(shí)例化過腔稀,就沒問題,如果正在顯示羽历,此時(shí)退出app焊虏,對(duì)話框會(huì)銷毀,并調(diào)用closeevent秕磷。dialog與displayElementPts一樣诵闭,也是單例方式創(chuàng)建的實(shí)例,由一個(gè)靜態(tài)的std::shared_ptr擁有著,他們的析構(gòu)次序是不確定的疏尿,所以程序會(huì)在退出的時(shí)候發(fā)生隨機(jī)的崩潰瘟芝。
輪到std::weak_ptr了,你雖不怎么關(guān)注它褥琐,或者幾乎沒用過它锌俱,但它并不像名字所示的那么弱。
class dialog{
static std::shared_ptr< dialog > instance(){...}
virtual void closeEvent(...){
if(!m_wp.expired())
m_wp->locked()->clear();
}
dialog()
{
//...
m_wp = displayElementPts::instance();
}
private:
std::weak_ptr< displayElementPts > m_wp;
}
先用expired()判斷單實(shí)例是否有效敌呈,再用locked取得有效的指針贸宏。就能避免獲取或者不能獲取有效實(shí)例的問題。
有沒有帶著鐐銬跳舞的感覺磕洪,其實(shí)不然吭练,只是在特殊的事件里才需要判斷,其它的位置析显,直接調(diào)用locked就好了线脚。
請(qǐng)安心享用std::shared_ptr吧。