o0o*_*o0o 10 reference-counting rust
我有以下代码使用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);
}
Run Code Online (Sandbox Code Playgroud)
sit*_*tif 25
看看描述中给出的示例,我认为这里真正的问题是“何时使用Rc与&Box”(注意&符号)。
两者Rc都&Box将底层数据存储在堆上,两者都不能跨线程发送,并且都允许不可变共享(由上述示例演示)。然而,最大的区别在于,它Rc为您提供了共享(不可变)的拥有值,同时&Box您获得了共享(不可变)引用。
在这种Rc情况下,每当最后一个所有者(无论是原始所有者还是任何克隆的所有者)被删除时,底层数据都会被删除(释放/解除分配)\xe2\x80\x93,这就是引用计数的想法。然而,在这种&Box情况下,只有一个所有者:在所有者超出范围后,对其的任何共享引用都将立即变得无效。
换句话说,与 a 相反Rc::clone(),将变量绑定到 new &Box(let a2 = &a;在示例中)不会使其寿命比其他情况更长。
作为一个具体示例,以下内容是有效的:
\nuse 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}\nRun Code Online (Sandbox Code Playgroud)\n但这不是:
\nfn 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}\nRun Code Online (Sandbox Code Playgroud)\n
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用于多线程共享使用)并记住您将需要Cell或RefCell内部可变性.