RustにおけるDerefとDropトレイトの活用

DerefとDropの概要

スマートポインタの「スマート」とは、単なるポインタに加えて、追加の機能を備えていることを意味します。その多くは、Rustのトレイト(trait)によって実現されており、DerefとDropはその代表例です。

Deref:データへのアクセスを簡潔に

Derefトレイトは、スマートポインタが通常の参照(&)と同様に扱えるようにする仕組みです。これにより、間接参照(*)演算子を使うことなく、ポインタが指す値に直接アクセスできます。

Box型でのDerefの実装例


impl<T: ?Sized> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.value
    }
}

このように、derefメソッドを実装することで、MyBox<T>型のインスタンスを通常の参照として扱えるようになります。

暗黙的な型変換のサポート

Rustコンパイラは、Derefトレイトを自動的に適用して、以下のような型変換をサポートします:

  • &T から &U(T: Deref<Target=U> の場合)
  • &mut T から &mut U(T: DerefMut<Target=U> の場合)
  • &mut T から &U(T: Deref<Target=U> の場合)

コード例


use std::ops::Deref;

struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> {
        MyBox(x)
    }
}

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

fn main() {
    let x = 5;
    let y = MyBox::new(x);

    assert_eq!(5, *y);
}

Drop:リソースの自動解放

Dropトレイトは、変数がスコープを離れる際に自動的に呼ばれるメソッドを定義します。これにより、ファイルハンドル、メモリ領域、ネットワーク接続などのリソースを安全に解放できます。

Dropの基本的な使い方


struct CustomSmartPointer {
    data: String,
}

impl Drop for CustomSmartPointer {
    fn drop(&mut self) {
        println!("'{}' のリソースを解放中", self.data);
    }
}

fn main() {
    {
        let _c = CustomSmartPointer { data: String::from("テストデータ") };
    }
    println!("mainの処理を継続");
}

明示的な解放

Dropトレイトのdropメソッドは直接呼び出すことはできませんが、std::mem::drop関数を使って明示的にリソースを解放できます。

Box型におけるDropの実装


unsafe impl<T: ?Sized> Drop for Box<T> {
    fn drop(&mut self) {
        let ptr = self.0.as_ptr();
        unsafe {
            if Layout::for_value_raw(ptr).size() != 0 {
                // ヒープ領域の解放処理
            }
        }
    }
}

その他のスマートポインタとDeref/Dropの関係

RefCellとCell

RefCellやCellはDerefを実装していません。そのため、通常の参照のようにアクセスすることはできません。代わりに、borrowやgetなどのメソッドを使用して値にアクセスします。

RcとArc

Rc(参照カウント型スマートポインタ)やArc(スレッドセーフな参照カウント型スマートポインタ)はDerefを実装しているため、通常の参照のように扱えます。


use std::rc::Rc;

fn main() {
    let data = Rc::new(vec![1, 2, 3, 4, 5]);
    let data_clone = Rc::clone(&data);

    println!("データの2番目の値: {}", data_clone[1]);
}

タグ: rust Deref Drop スマートポインタ トレイト

7月22日 01:26 投稿