Rust - 智能指针

  • 简述

    默认情况下,Rust 分配堆栈上的所有内容。您可以通过将它们包装在像Box这样的智能指针中来将它们存储在堆上。像 Vec 和 String 这样的类型隐式地帮助堆分配。智能指针实现下表中列出的特征。智能指针的这些特征将它们与普通结构区分开来 -
    序号 Trait 名 包 & 描述
    1 Deref
    std::ops::Deref
    用于不可变的解引用操作,如 *v。
    2 Drop
    std::ops::Drop
    用于在值超出范围时运行一些代码。这有时称为析构函数
    在本章中,我们将了解 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 trait 要求我们实现一个名为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 trait 包含drop()方法。当实现此特征的结构超出范围时,将调用此方法。在某些语言中,程序员每次完成使用智能指针实例时都必须调用代码来释放内存或资源。在 Rust 中,您可以使用 Drop trait 实现自动内存释放。
    
    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