Drop

トレイトについて学びましたので、Rustの標準ライブラリによって提供されている具体的なトレイト Dropについて説明しましょう。 Drop トレイトは値がスコープ外になった時にコードを実行する方法を提供します:

struct HasDrop; impl Drop for HasDrop { fn drop(&mut self) { println!("Dropping!"); } } fn main() { let x = HasDrop; // do stuff // いくつかの処理 // } // x goes out of scope here } // x はここでスコープ外になります
struct HasDrop;

impl Drop for HasDrop {
    fn drop(&mut self) {
        println!("Dropping!");
    }
}

fn main() {
    let x = HasDrop;

    // いくつかの処理

} // x はここでスコープ外になります

xmain() の終わりでスコープ外になった時、 Drop のコードが実行されます。 Dropdrop() と呼ばれるミュータブルな self への参照を引数に取るメソッドを持っています。

これだけです! Drop のメカニズムは非常にシンプルです、しかし少しだけ注意すべき点があります。 たとえば、値がドロップされる順序は、それらが定義された順序と反対の順序になります:

struct Firework { strength: i32, } impl Drop for Firework { fn drop(&mut self) { println!("BOOM times {}!!!", self.strength); } } fn main() { let firecracker = Firework { strength: 1 }; let tnt = Firework { strength: 100 }; }
struct Firework {
    strength: i32,
}

impl Drop for Firework {
    fn drop(&mut self) {
        println!("BOOM times {}!!!", self.strength);
    }
}

fn main() {
    let firecracker = Firework { strength: 1 };
    let tnt = Firework { strength: 100 };
}

このコードは以下の様な出力をします:

BOOM times 100!!!
BOOM times 1!!!

TNTが爆竹(firecracker)が鳴る前に爆発してしまいました、これはTNTが定義されたのは爆竹よりも後だったことによります。 ラストイン・ファーストアウトです。

Drop は何をするのに適しているのでしょうか?一般的に Dropstruct に関連付けられているリソースのクリーンアップに利用されます。 たとえば、 Arc<T> は参照カウントを行う型です。 Drop が呼ばれると、参照カウントがデクリメントされ、 もし参照の合計数が0になっていたら、内包している値がクリーンアップされます。