我有以下代码,它同时使用Rc
和Box
;那些有什么区别?哪一个更好?
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);
}
答案 0 :(得分:7)
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
}
此外,{}不能在线程之间发送Rc
,因为它没有实现Send
。
底线是它们用于不同的事情:如果您不需要共享访问权限,请使用Box
;否则,请使用Rc
(或Arc
进行多线程共享使用),请注意,内部可变性需要Cell
或RefCell
。
答案 1 :(得分:2)
查看说明中给出的示例,我认为这里真正的问题是“何时使用 Rc
与 &Box
”(注意与符号)。
Rc
和 &Box
都将底层数据存储在堆上,都不能跨线程发送,并且都允许不可变共享(由上述示例演示)。但是,最大的区别是 Rc
为您提供共享(不可变)拥有值,而 &Box
为您提供共享(不可变)引用 .
在 Rc
的情况下,只要最后一个所有者(无论是原始所有者还是任何克隆所有者)被删除,底层数据就会被删除(释放/释放)——这就是引用计数的想法。但是,在 &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.
}