何时使用 Rc 与 Box?
When to use Rc vs Box?
我有以下同时使用 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); //=> 1 1
println!("{} {}", b1, b2); //=> 1 1
}
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 共享用法)并记住您将需要 Cell
或 RefCell
以实现内部可变性。
查看描述中给出的示例,我认为这里真正的问题是“何时使用 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.
}
我有以下同时使用 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); //=> 1 1
println!("{} {}", b1, b2); //=> 1 1
}
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 共享用法)并记住您将需要 Cell
或 RefCell
以实现内部可变性。
查看描述中给出的示例,我认为这里真正的问题是“何时使用 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.
}