Rust - 智慧指標



Rust 預設情況下將所有內容分配在棧上。您可以透過將它們包裝在智慧指標(如Box)中來將內容儲存在堆上。像 Vec 和 String 這樣的型別隱式地幫助堆分配。智慧指標實現了下表中列出的特徵。這些特徵將智慧指標與普通的結構體區分開來:

序號 特徵名稱 包 & 描述
1 Deref

std::ops::Deref

用於不可變的解引用操作,例如 *v。

2 Drop

std::ops::Drop

用於在值超出作用域時執行某些程式碼。這有時被稱為解構函式

在本章中,我們將學習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 特徵

標準庫提供的 Deref 特徵要求我們實現一個名為deref的方法,該方法借用self並返回對內部資料的引用。以下示例建立了一個結構體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 特徵

Drop 特徵包含drop()方法。當實現此特徵的結構體超出作用域時,將呼叫此方法。在某些語言中,程式設計師必須在每次完成使用智慧指標例項後呼叫程式碼來釋放記憶體或資源。在 Rust 中,您可以使用 Drop 特徵實現自動記憶體釋放。

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");
}

在上面的示例中,drop 方法將被呼叫兩次,因為我們在堆中建立了兩個物件。

dropping MyBox object from memory
dropping MyBox object from memory
廣告

© . All rights reserved.