Drop トレイト
Drop を実装する値は、スコープを抜けるときに実行するコードを指定できます:
// 著作権 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 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 innermost block"); } println!("Exiting next block"); } drop(a); println!("Exiting main"); }
std::mem::dropはstd::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()に置き換えてみてください。