何时使用 Rc 与 Box?

When to use Rc vs Box?

我有以下同时使用 RcBox 的代码;这些有什么区别?哪个更好?

use std::rc::Rc;

fn main() {
    let a = Box::new(1);
    let a1 = &a;
    let a2 = &a;
    let b = Rc::new(1);
    let b1 = b.clone();
    let b2 = b.clone();

    println!("{} {}", a1, a2); //=> 1 1
    println!("{} {}", b1, b2); //=> 1 1
}

playground link

Rc provides shared ownership so by default its contents can't be mutated, while Box 提供专有所有权,因此允许更改:

use std::rc::Rc;

fn main() {
    let mut a = Box::new(1);
    let mut b = Rc::new(1);

    *a = 2; // works
    *b = 2; // doesn't
}

另外Rc不能在线程间发送,因为它没有实现Send.

最重要的是它们的用途不同:如果您不需要共享访问权限,请使用 Box;否则,请使用 Rc(或 Arc 用于 multi-threaded 共享用法)并记住您将需要 CellRefCell 以实现内部可变性。

查看描述中给出的示例,我认为这里真正的问题是“何时使用 Rc&Box”(注意和号)。

Rc&Box都将底层数据存储在堆上,都不能跨线程发送,都允许不可变共享(由上述示例演示)。然而,最大的区别是 Rc 给你一个共享的(不可变的)owned 值,而 &Box 你得到一个共享的(不可变的)参考.

Rc 的情况下,每当最后一个所有者(无论是原始所有者还是任何克隆的所有者)被删除时,基础数据将被删除(freed/deallocated)——这就是引用计数的想法.但是,在 &Box 的情况下,只有一个所有者:在所有者离开范围后,对它的任何共享引用都将立即失效。

换句话说,与 Rc::clone() 相反,将变量绑定到新的 &Box(示例中的 let a2 = &a;)不会使它的寿命比其他情况更长。

作为具体示例,以下内容有效:

use std::rc::Rc;

fn main() {
    let rc_clone;
    {
        let rc = Rc::new(1);
        rc_clone = rc.clone();
        // rc gets out of scope here but as a "shared owner", rc_clone
        // keeps the underlying data alive.
    }
    println!("{}", rc_clone);  // Ok.
}

但这不是:

fn main() {
    let b_ref;
    {
        let b = Box::new(1);
        b_ref = &b;
        // b gets out of scope here and since it is the only owner,
        // the underlying data gets dropped.
    }
    println!("{}", b_ref); // Compilation error: `b` does not live long enough.
}