Drop 特徵

如果值實作了 Drop,即可在超出範圍時指定要執行哪個程式碼:

struct Droppable {
    name: &'static str,
}

impl Drop for Droppable {
    fn drop(&mut self) {
        println!("Dropping {}", self.name);
    }
}

fn main() {
    let a = Droppable { name: "a" };
    {
        let b = Droppable { name: "b" };
        {
            let c = Droppable { name: "c" };
            let d = Droppable { name: "d" };
            println!("Exiting block B");
        }
        println!("Exiting block A");
    }
    drop(a);
    println!("Exiting main");
}
This slide should take about 8 minutes.
  • 請注意,std::mem::dropstd::ops::Drop::drop 不同。
  • 值超出範圍時,系統會自動捨棄。
  • 捨棄值時,如果值實作的是 std::ops::Drop,系統會呼叫值的 Drop::drop 實作。
  • 如此一來,無論值是否實作 Drop,系統都會一併捨棄值的所有欄位。
  • std::mem::drop 只是一個可接受任何值的空白函式。此函式之所以重要,是能夠取得值的擁有權,因此在其範圍結束時會遭到捨棄。這有利於在值超出範圍之前,明確捨棄這些值。
    • 如果物件會對 drop 執行某些工作 (例如釋放鎖、關閉檔案等),這就相當實用。

討論要點:

  • 為什麼 Drop::drop 不使用 self
    • 簡答:如果這樣的話,系統會在 區塊結尾呼叫 std::mem::drop,進而觸發另一個對 Drop::drop 的呼叫並造成堆疊 溢位!
  • 請嘗試將 drop(a) 替換為 a.drop()