当前位置:   article > 正文

RUST 笔记(八)_rust self.0

rust self.0

智能指针

特性

  1. 通过 Deref trait 将智能指针当作常规引用处理

  2. 通过解引用运算符 * 追踪指针的值

  3. 为了启用 * 运算符的解引用功能,需要实现 Deref trait。

    use std::ops::Deref;
    
    impl<T> Deref for MyBox<T> {
        type Target = T;
    
        fn deref(&self) -> &T {
            &self.0
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  4. 解引用强制多态。解引用强制多态是 Rust 表现在函数或方法传参上的一种便利,实现了 Deref 的类型的引用转换为原始类型通过 Deref 所能够转换的类型的引用。解引用强制多态与可变性交互,类型和 trait 实现满足三种情况时会进行解引用强制多态

    • 当 T: Deref<Target=U> 时从 &T 到 &U。 // 不可变
    • 当 T: DerefMut<Target=U> 时从 &mut T 到 &mut U。 // 可变
    • 当 T: Deref<Target=U> 时从 &mut T 到 &U。// 从不可变到可变
  5. 使用 Drop Trait 运行清理代码。指定在值离开作用域时应该执行的代码的方式是实现 Drop trait。Drop trait 要求实现一个叫做 drop 的方法,它获取一个 self 的可变引用。通过 std::mem::drop 提早丢弃值。


标准库中的指针

Box<T> 在堆上存数据,并且可确定大小

  1. box 允许你将一个值放在堆上而不是栈上。留在栈上的则是指向堆数据的指针

  2. Box 类型是一个智能指针,因为它实现了 Deref trait,它允许 Box 值被当作引用对待。当 Box 值离开作用域时,由于 Box 类型 Drop trait 的实现,box 所指向的堆数据也会被清除

    enum List {
        Cons(i32, Box<List>),
        Nil,
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

Rc<T> 引用计数智能指针

  1. 大部分情况下所有权是非常明确的:可以准确的知道哪个变量拥有某个值。然而,有些情况单个值可能会有多个所有者。
  2. 为了启用多所有权,Rust 有一个叫做 Rc 的类型,即引用计数。克隆 Rc 会增加引用计数,如果某个值有零个引用,就代表没有任何有效引用并可以被清理。
  3. 使用场景,如使用 Rc 共享数据
    enum List {
        Cons(i32, Rc<List>),
        Nil,
    }
    
    use List::{Cons, Nil};
    use std::rc::Rc;
    
    fn main() {
        let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
        let b = Cons(3, Rc::clone(&a));
        let c = Cons(4, Rc::clone(&a));
        println!("count after creating c = {}", Rc::strong_count(&a));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

RefCell<T> 和内部可变性模式

  1. 内部可变性是 Rust 中的一个设计模式,它允许你即使在有不可变引用时改变数据,这通常是借用规则所不允许的.
  2. 通过 RefCell<T> 在运行时检查借用规则
  3. 内部可变性使用场景如:mock 对象,接口不可变,但测试时需要改变
  4. 结合 Rc<T> 和 RefCell<T> 来拥有多个可变数据所有者

智能指针可能造成引用循环与内存泄漏

  1. 避免引用循环:将 Rc 变为 Weak 弱引用。其区别在于 weak_count 无需计数为 0 就能使 Rc 实例被清理。

  2. 一个常见的例子是树节点,子引用父弱引用,父列举子强引用。释放父节点时子节点必须释放,释放子节点时父节点不必释放。

    truct Node {
        value: i32,
        parent: RefCell<Weak<Node>>,
        children: RefCell<Vec<Rc<Node>>>,
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    通过在 Node 定义中指定从子结点到父结点的关系为一个Weak引用,就能够拥有父结点和子结点之间的双向引用而不会造成引用循环和内存泄露。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/951230
推荐阅读
相关标签
  

闽ICP备14008679号