什么时候使用Rc vs Box?

o0o*_*o0o 10 reference-counting rust

我有以下代码使用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);
    println!("{} {}", b1, b2);
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接

sit*_*tif 25

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

\n

两者Rc&Box将底层数据存储在堆上,两者都不能跨线程发送,并且都允许不可变共享(由上述示例演示)。然而,最大的区别在于,它Rc为您提供了共享(不可变)的拥有值,同时&Box您获得了共享(不可变)引用

\n

在这种Rc情况下,每当最后一个所有者(无论是原始所有者还是任何克隆的所有者)被删除时,底层数据都会被删除(释放/解除分配)\xe2\x80\x93,这就是引用计数的想法。然而,在这种&Box情况下,只有一个所有者:在所有者超出范围后,对其的任何共享引用都将立即变得无效。

\n

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

\n

作为一个具体示例,以下内容是有效的:

\n
use std::rc::Rc;\n\nfn main() {\n    let rc_clone;\n    {\n        let rc = Rc::new(1);\n        rc_clone = rc.clone();\n        // rc gets out of scope here but as a "shared owner", rc_clone\n        // keeps the underlying data alive.\n    }\n    println!("{}", rc_clone);  // Ok.\n}\n
Run Code Online (Sandbox Code Playgroud)\n

但这不是:

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

  • 我的目的只是想分享事情是如何工作的,而不是人们应该使用什么,但你有一个很好的观点,不要使用 `&Box<T>`! (6认同)
  • 您可能不想使用 `&Box<T>` 而是使用 `&T` 。Box 实现了 `Deref<Target=T>`,因此您只需执行 `&*my_box` 即可获得 `&T`。 (3认同)

lje*_*drz 10

Rc提供共享所有权,因此默认情况下其内容不能变异,同时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
}
Run Code Online (Sandbox Code Playgroud)

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

最重要的是它们用于不同的事情:如果您不需要共享访问,请使用Box; 否则,使用Rc(或Arc用于多线程共享使用)并记住您将需要CellRefCell内部可变性.