[rust]Rc智能指针

35 阅读2分钟

定义

Rc(Reference Counted)智能指针是 Rust 标准库中的一个引用计数类型,它允许多个所有者共享同一个值

相关概念:

  1. 共享所有权:多个 Rc 指针可以同时指向同一个数据,通过克隆来创建新的共享所有者
  2. 引用计数:每当 Rc 指针进行克隆时,引用计数增加;当一个 Rc指针 超出作用域时,引用计数减少。只有当引用计数为零时,数据才会被真正销毁
  3. 不可变:Rc 本身是不可变的,即通过 Rc 不能直接修改其内部的数据。如果需要可变共享数据,可以结合 RefCell 使用
  4. 只适用于单线程:Rc 的引用计数不是线程安全的,因此它只适用于单线程场景。如果你需要在多线程环境中使用,可以使用 Arc(Atomic Reference Counted)类型,它的引用计数是线程安全的

引言

image.png

我们需要实现一个如上结构的链表:

enum List{
    Next(i32,Box<List>),
    Nil
}

fn main() {
  use List::{Next,Nil};
    let a = Next(5, Box::new(Next(10,Box::new(Nil))));
    let b = Next(3, Box::new(a));
    let c = Next(4, Box::new(a));
}

第10行代码编译报错:value used here after move

a的值所有权已经给了b,则c不能再使用了,当这种多个变量需要共享同一个变量所有权的情况下就需要用到Rc智能指针

error[E0382]: use of moved value: `a`
   --> src/main.rs:118:30
    |
116 |     let a = Next(5, Box::new(Next(10,Box::new(Nil))));
    |         - move occurs because `a` has type `List`, which does not implement the `Copy` trait
117 |     let b = Next(3, Box::new(a));
    |                              - value moved here
118 |     let c = Next(4, Box::new(a));
    |                              ^ value used here after move

Rc共享所有权

use std::rc::Rc;
enum List{
    Next(i32,Rc<List>),
    Nil
}

fn main() {
  use List::{Next,Nil};
    let a = Rc::new(Next(5, Rc::new(Next(10,Rc::new(Nil)))));
    let b = Next(3, Rc::clone(&a));
    let c = Next(4, Rc::clone(&a));

    println!("*********")
}

方式二

fn main() {
  use List::{Next,Nil};
    let a = Rc::new(Next(5, Rc::new(Next(10,Rc::new(Nil)))));
    let b = Next(3, a.clone()); // 直接调用Rc变量的clone方法
    let c = Next(4, a.clone());

    println!("*********")
}

Rc引用计数

fn main() {
    use List::{Next, Nil};
    let a = Rc::new(Next(5, Rc::new(Next(10, Rc::new(Nil)))));
    println!("count after creating a = {}", Rc::strong_count(&a));

    let b = Next(3, a.clone());
    println!("count after bind to b, a count = {}", Rc::strong_count(&a));

    {
        let c = Next(4, a.clone());
        println!("count after bind to c, a count = {}", Rc::strong_count(&a));
    }

    println!("count end, a count = {}", Rc::strong_count(&a));
}

//  输出:
// count after creating a = 1
// count after bind to b, a count = 2
// count after bind to c, a count = 3
// count end, a count = 2