Rust-smart-pointers

提供:Dev Guides
移動先:案内検索

Rust-スマートポインター

Rustはデフォルトでスタック上のすべてを割り当てます。 _Box_のようなスマートポインターでラップすることで、ヒープに物を保存できます。 VecやStringなどの型は、暗黙的にヒープの割り当てに役立ちます。 スマートポインターは、以下の表にリストされている特性を実装します。 スマートポインターのこれらの特性は、通常の構造体と区別します-

Sr.No Trait name Package & Description
1 Deref

std::ops::Deref

  • vなどの不変の逆参照操作に使用されます。
2 Drop
  • std::ops::Drop*

値が範囲外になったときにいくつかのコードを実行するために使用されます。 これは_destructor_と呼ばれることもあります

この章では、 Box スマートポインターについて学習します。 また、Boxのようなカスタムスマートポインターを作成する方法も学習します。

Box

ボックスとも呼ばれるBoxスマートポインターを使用すると、スタックではなくヒープにデータを保存できます。 スタックには、ヒープデータへのポインターが含まれています。 Boxには、データをヒープに保存する以外に、パフォーマンスのオーバーヘッドはありません。

ボックスを使用してi32値をヒープに格納する方法を見てみましょう。

fn main() {
   let var_i32 = 5;
  //stack
   let b = Box::new(var_i32);
  //heap
   println!("b = {}", b);
}

出力

b = 5

変数が指す値にアクセスするには、参照解除を使用します。 *は間接参照演算子として使用されます。 Boxで間接参照を使用する方法を見てみましょう。

fn main() {
   let x = 5;
  //value type variable
   let y = Box::new(x);
  //y points to a new value 5 in the heap

   println!("{}",5==x);
   println!("{}",5==*y);
  //dereferencing y
}

変数xは、値が5の値型です。 したがって、式_5 == x_はtrueを返します。 変数yはヒープを指します。 ヒープ内の値にアクセスするには、_ yを使用して逆参照する必要があります。 y_は値5を返します。 したがって、式_5 == *y_はtrueを返します。

出力

true
true

イラスト-Deref Trait

標準ライブラリが提供するDerefトレイトでは、self_を借用して内部データへの参照を返す_deref_という名前のメソッドを実装する必要があります。 次の例では、ジェネリック型である_MyBox_構造体を作成します。 特性_Deref_を実装します。 この特性は、* y_を使用して_y_でラップされたヒープ値にアクセスするのに役立ちます。

use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
  //Generic structure with static method new
   fn new(x:T)-> MyBox<T> {
      MyBox(x)
   }
}
impl<T> Deref for MyBox<T> {
   type Target = T;
   fn deref(&self) -> &T {
      &self.0//returns data
   }
}
fn main() {
   let x = 5;
   let y = MyBox::new(x);
  //calling static method

   println!("5==x is {}",5==x);
   println!("5==*y is {}",5==*y);
  //dereferencing y
   println!("x==*y is {}",x==*y);
  //dereferencing y
}

出力

5==x is true
5==*y is true
x==*y is true

イラスト-ドロップ特性

ドロップ特性には_drop()_メソッドが含まれています。 このメソッドは、この特性を実装した構造が範囲外になると呼び出されます。 一部の言語では、プログラマーはスマートポインターのインスタンスの使用を終了するたびに、メモリまたはリソースを解放するコードを呼び出す必要があります。 Rustでは、ドロップ特性を使用して自動メモリ割り当て解除を実現できます。

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
   }
}
impl<T> Drop for MyBox<T>{
   fn drop(&mut self){
      println!("dropping MyBox object from memory ");
   }
}
fn main() {
   let x = 50;
   MyBox::new(x);
   MyBox::new("Hello");
}

上記の例では、ヒープに2つのオブジェクトを作成しているため、dropメソッドが2回呼び出されます。

dropping MyBox object from memory
dropping MyBox object from memory