std::weak_ptr(弱參考智慧指標)
std::shared_ptr 透過計數擁有者來讓物件存活——但有時你想指向一個共享物件卻不成為它的擁有者之一,好讓你的指標既不延續它的生命、也不製造環。std::weak_ptr 正是如此:一個對 shared_ptr 所管理物件的非擁有觀察者。它能告訴你物件是否仍存活,並在存活時讓你安全地取得一個暫時的擁有指標,但它本身永遠不會阻止物件被銷毀。
具體而言,weak_ptr 參照與那些 shared_ptr 相同的控制區塊,卻不貢獻強參考計數(它增加的是另一個弱計數,只決定控制區塊本身何時可被釋放)。當你真的需要使用物件時,你呼叫 .lock(),它原子地檢查強計數:若物件仍存活,它回傳一個全新的 shared_ptr(短暫提高計數,這樣物件就不會在你手中消失);若它已被銷毀,則回傳一個空的 shared_ptr。你也可以呼叫 .expired() 來問「它走了嗎?」。這是持有「也許還在」連結卻既不洩漏也不解參考已死物件的安全方式。
為何重要:典型用途是打破參考環。若父物件的 shared_ptr 指向子物件,而子物件也需要回指它的父物件,把那個回指做成 weak_ptr 就能讓計數歸零、物件正確釋放。weak_ptr 也是快取與觀察者清單的正確工具,因為它們不該讓目標物件存活。誠實的要點:weak_ptr 不是你能直接解參考的指標——你必須先 lock() 它,並且必須檢查結果,因為物件可能在你上次檢查與此刻之間已被銷毀。
std::weak_ptr<Node> w = parent; if (auto p = w.lock()) { use(*p); } else { /* parent 已經消失 */ }
只有在物件仍存活時 lock() 才回傳可用的 shared_ptr;否則回傳空值,因此不會有懸置的解參考。
weak_ptr 不延長生存期,所以 .expired() 現在為假,在多執行緒程式裡並不保證物件能撐到你的下一行——只有 lock() 回傳的 shared_ptr 才保證。當你打算碰觸物件時,請使用 lock() 的結果,而非另外一次 expired() 檢查。