範圍綁定的確定性解構(scope-bound deterministic destruction)
想像借來的書有兩種歸還方式。第一種,你承諾「總有一天」會還,圖書館員或許哪天會來敲你的門——這就是垃圾回收。第二種,你一讀完、從書桌站起的那一刻,書就立刻被歸還,每次都是,而且時間點你指得出來。C++ 採用第二種模型,這種精確又可預測的時機,我們稱為確定性解構。
具體來說:每個物件都有生存期,對於自動儲存期的物件(區域變數),生存期在所屬區塊的右大括號處結束,並以建構的相反順序進行。就在那個精確的時間點,解構子執行。沒有背景回收器、沒有停頓、也沒有「何時」的疑問。若函式裡有 a、b、c 三個物件,範圍離開時會以 c、b、a 的順序銷毀——而若中途丟出例外,已建構的物件仍會在堆疊輾轉展開時以相反順序被銷毀。這正是 RAII 之所以可靠的原因:「清理何時發生」有唯一且可知的答案。
對系統程式設計為何重要:當你持有一把鎖、一個檔案描述符或一個硬體暫存器時,你通常非常在意它究竟何時被釋放——太晚意味著競爭或資源耗盡;在不確定的 GC 停頓中釋放對延遲會是場災難。確定性是這份交易:C++ 給你精確的控制與時機,交換條件是你(或你的 RAII 型別)要為正確性負責。提醒:動態儲存期物件(沒有 RAII 的 new)、thread_local 與靜態物件有著不同、有時令人意外的銷毀時機——只有自動儲存期物件享有「到大括號就乾淨收尾」的保證。
void f() { Logger a; Buffer b; /* ... */ } // 到大括號:先執行 ~Buffer(),再執行 ~Logger()——建構順序的相反
最後建構者最先銷毀——而且時機精確,不是「總有一天」。
確定性不代表你擁有的一切都瞬間完成:若 a 是指向百萬節點樹的 unique_ptr,它的解構子仍會在那個大括號處走遍並釋放整棵樹,這可能花費可觀的時間。可預測的時機不等於零成本。