RcArc

  • 用于共享所有权。
  • 允许多个所有者,数据在最后一个 Rc 销毁时释放。
  • 适合跨作用域或复杂数据结构共享数据。

Rc<T>

use std::rc::Rc;

fn main() {
  let a = String::from("hello");
  let b = a;
  // let c = a;
  //         ^ 这里将报错,因为a的所有权被移交给了b

  println!("{}", b);


  let d = Rc::new(b);
  // 使用 Rc::strong_count 可以获取Rc类型的引用次数
  let f = Rc::strong_count(&d);
  println!("d的引用次数 {f}");

  // 使用Rc::clone可以克隆一份智能指针,使得对应的Rc引用次数+1
  // 也可以使用 .clone() 方法。但是为了可读性(避免被认为是Copy trait的方法)更推荐使用Rc::clone
  // Rc::clone 仅仅复制了智能指针,并增加引用计数,这与Copy trait的clone(克隆底层数据)有着本质区别。
  let e = Rc::clone(&d); // 引用次数+1
  let f = Rc::strong_count(&d);
  println!("d的引用次数 {f}");

  assert_eq!(Rc::strong_count(&d), Rc::strong_count(&e));

  {
    let g = d.clone(); // 这里发生 +1
    let f = Rc::strong_count(&d);
    println!("d的引用次数 {f}");
  } // g离开作用域 g被drop, Rc引用 -1

  let f = Rc::strong_count(&d);
  println!("d的引用次数 {f}");
}

&T的区别

use std::rc::Rc;

#[allow(unused)]
fn main() {
  let a = String::from("hello");
  let a1 = &a;
  let a2 = &a;
  let a3 = &a;
  
  let b = Rc::new(String::from("hello"));
  let b1 = Rc::clone(&b);
  let b2 = Rc::clone(&b);
  let b3 = Rc::clone(&b);
}

&a不也可以实现多次引用吗,为什么还需要Rc

&a
&a

举两个简单的例子

函数返回引用/Rc

use std::rc::Rc;

#[allow(unused)]
fn main() {
  fn return_borrow() {
    let s = String::from("hello");
    // &s
    // ^ 这里如果返回 &s 将造成悬垂引用。代码报错
  }

  fn return_rc() -> Rc<String> {
    let s = Rc::new(String::from("hello"));
    s
    // 可以返回,交给Rc 管理生命周期
  }


  return_borrow(); // 如果非要函数体内部的数据,智能返回一个数据本体(非引用)
  let s = return_rc();
  println!("{}", s); // 无惧声明周期 继续访问

}

提前drop

use std::rc::Rc;

#[allow(unused)]
fn main() {
  fn drop_borrow() {
    struct Wrapper<'a>(&'a String);

    let s = String::from("hello");
    let w = Wrapper(&s);
    std::mem::drop(s);
    // println!("{}", w.0);
    //                ^^^ 再访问w将发生报错 因为s被drop 发生悬垂引用
  }

  fn drop_rc() {
    struct  Wrapper(Rc<String>);
    let s = Rc::new(String::from("hello"));

    let w = Wrapper(Rc::clone(&s));

    std::mem::drop(s);
    println!("{}", w.0);
    // 虽然s被drop 但w不受影响😎
  }

  drop_borrow();
  drop_rc();
}

Arc<T>

Rc只能在单线程中共享数据。
Arc可以在多线程中共享数据。

fn main() {
  // let s = Rc::new(String::from("hello"));
  //         ^^^^^ 没有实现Send trait
  let s = std::sync::Arc::new(String::from("hello"));
  for index in 0..10 {
    let s_ = s.clone();
    let handle = std::thread::spawn(move || {
      println!("in {}, {}", index, s_)
    });
  }
  println!("world")
}