C++有一个类似的、非常受欢迎的问题,但我找不到类似的 Rust 现有问题。
那么,Rust 中Box
、Rc
、Ref
、RefMut
(其他?)的用例是什么?
问题的重要部分(对我个人而言):什么时候应该使用智能指针而不是引用?
我知道The Rust Book非常非常彻底地解释了它,但我希望在这个主题上有一个简洁而快速的"备忘单",可能有一些书中缺少的真实世界的例子。
Rust 中
Box
、Rc
、Ref
、RefMut
(其他?)的用例是什么?
好的,我们开始:
Box
,用最简单的术语来说,当您有一个要保留在堆上的对象时。在以下情况下使用框- 您希望拥有动态大小的对象
- 您希望将对象泄漏到
'static
生命周期中 - 你想要生成一个 ffi 指针
- 你想要制作递归类型
- 当很难确定对象的生存期时,将使用
Rc
。这是懒惰过度使用的表现,在某种程度上违背了一生的目的。 Ref
和RefMut
是RefCell
在您尝试访问其内容时生成的对象。RefCell
将在运行时而不是编译时跟踪其对象的借用状态,因此它有点像生命周期。例如,当您需要在哈希映射中具有对许多对象的可变引用时,这是通常的用途。Arc
与RwLock
(与RefCell
基本相同,除了下面的内容)或Mutex
一起使用,尝试跨线程边界共享对象。他们页面上的示例将向您展示如何使用它们以及为什么它们与使用Rc<RefCell<T>>
模式相比很重要。
在 rust 中本身还有一些"智能"指针,但你必须知道的是,除非您使用不安全的代码或直接使用全局分配器,否则所有内容最终都会取消分配其内容。
这与为什么语言中内置的工具(生命周期)对 Rust 如此重要有关,它们完成了Rc
和RefCell
完成的所有工作,但没有性能缺陷,并且还可以在没有 UB 机会的情况下做C/C++
做的事情。
我会给出的简单答案是:尽可能使用引用。 不幸的是,了解何时可以取决于对借用检查器的更深入理解,到那时,我想备忘单会不那么有用。 但是,一些简单的解释可能会有所帮助。
- 简单的情况是,您有一个明确的所有者,并且引用沿堆栈向下传递到您调用的函数。 这种情况显然仅适用于参考。
- 如果您拥有相同的明确所有权,但商品"大"或尺寸不确定,您可能需要
Box
。 仍然是单一所有者,可能基于堆栈的借款。 - 当所有权不在树中时,
Rc
或Arc
是合适的(带有共享Mutex
之类的东西)。
提到的其他事情(Ref
,RefMut
)是关于RefCell
中包含的事物的借用。Cell
和RefCell
是可变的容器。
我想说,首先尝试拥有您的物品,并使用借用的引用来传递它。 如果您确实需要共享,请查看Rc
或Arc
。 如果这仍然不起作用,请考虑其他事项。
不过,Rust Book 的描述非常好,你必须了解借
用才能直观地了解该怎么用。