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::dropself をパラメータとして取らないのはなぜですか?
    • 短い回答: その場合、ブロックの最後に std::mem::drop が呼び出されるため、別の Drop::drop が呼び出され、スタック オーバーフローが発生します。
  • drop(a)a.drop() に置き換えてみてください。