Sil*_*olo 10
让我们从 开始RefCell,根据我个人的经验,这是三者中最常用的。
通常,在 Rust 中,借用规则是在编译时检查的。您必须向编译器(实际上是向称为借用检查器的类似类型检查器的系统)证明您所做的一切都是公平的游戏:每个对象要么可变地借用一次,要么不可变地借用多次,并且这些对象两条线不交叉。RefCell将此检查移至运行时。您可以将 a 转换RefCell<T>为 a &T,borrow也可以将 a 转换RefCell<T>为&mut Twith [1]。borrow_mut
当您在运行时调用这些函数时,Rust 会检查通常的借用规则是否适用。您不必向类型检查器证明它有效,但如果事实证明您错了,您的程序将会出现恐慌[2]。我们没有改变规则;您刚刚将它们从编译时推到了运行时。这可能很有用,例如,如果您正在编写一个以某种复杂方式操作数据的递归算法,并且您亲自检查了借用规则是否得到遵守,但您无法向 Rust 证明这一点。
然后是Cell. ACell类似,但它不是基于参考的。相反, a 的基本操作Cell是replace。replace为单元格获取一个新值(按值),并且顾名思义,替换单元格的内容。在这种情况下不需要进行任何可变性检查,因为此操作是一举完成的。您调用该函数,该函数发挥其魔力,然后返回。它不会给你一个参考。上还有其他功能Cell,例如updateNightly Rust,但它们都是根据replace.
请注意,我们讨论的任何类型都不能跨线程共享。因此,在 的情况下Cell,不必担心一个线程试图替换该值,而另一个线程正在读取该值。在 的情况下RefCell,不需要复杂的锁定机制来协调运行时检查。
进入UnsafeCell。所有的安全检查都被移除了UnsafeCell。RefCell我们并没有将安全性推到运行时;而是将安全性推到了运行时。我们在后院拍摄并拍摄了它。的基本操作UnsafeCell是get,它与borrow_mutfor类似RefCell,只是它总是返回一个可变指针。它不会失败,不会抱怨竞争条件或共享数据,它只会给你一个指针。请注意,这*mut T是一个原始指针类型,修改该类型指针的唯一方法是使用Unsafe Rust。
UnsafeCell不应该直接使用。它是用于实现其他两种(安全)单元类型的编译器原语。如果您确实出于某种原因决定需要UnsafeCell,则需要非常小心地保留编译器有关数据访问的假设,因为当您开始涉足 Unsafe Rust 时,很容易使事情变得非常错误。相信我,我是根据经验说的。上次我unsafe编写一些代码时,它开始引起足够多的问题,以至于我最终使用(安全)原语重写了整个代码,但从未真正弄清楚出了什么问题。它很快就会变得混乱。
[1]您实际上将 a 分别转换为名为和RefCell<T>的专用类型,但这些类型被设计为像普通引用一样运行,因此为了简洁起见,我省略了该细节。Ref<'_, T>RefMut<'_, T>
[2]这些函数有一些变体try_borrow,try_borrow_mut它们会返回 aResult而不是在失败时恐慌。
| 归档时间: |
|
| 查看次数: |
3224 次 |
| 最近记录: |