Rust 盒装与非盒装

Tes*_*est 0 rust

给定一个 Rust 对象,是否可以将其包装起来,以便允许多个引用和可变引用,但不会导致问题?

例如, aVec具有多个引用和一个可变引用。

Sil*_*olo 7

对,但是...

您正在寻找的类型是RefCell,但在行动之前请继续阅读!

Rust 是一种单一所有权语言。永远都是这样。正是这个特性使得 Rust 成为线程安全和内存安全的。你无法完全规避这一点,除非将整个程序包装起来unsafe并专门使用原始指针,如果你打算这样做,只需编写 C,因为你不再从使用 Rust 中获得任何好处。

因此,在程序中的任何给定时刻,必须有一个内容写入该内存或读取多个内容。这是单一所有权的基本法则。记住这一点; 你无法回避这一点。我接下来要说的仍然遵循这个规则。

通常,我们通过类型签名来强制执行此操作。如果我使用 a &T,那么我只是一个别名,不会写入它。如果我采取了&mut T,那么在我放弃该参考之前,没有其他人可以看到我在做什么。这通常就足够好了,如果可以的话,我们希望这样做,因为我们在编译时得到了保证。

但事情并不总是这样。有时我们无法证明我们所做的事情是正确的。有时我有两个函数持有一个表面上可变的引用,但我知道,由于 Rust 不知道的其他一些保证,一次只有一个函数会写入它。进入RefCellRefCell<T>包含一个 singleT并假装是不可变的,但允许您通过try_borrow_mutand可变或不可变地借用内部的东西try_borrow。当我们调用这些函数之一时,我们会得到一个类似引用的值,该值可以读取(在可变情况下也可以写入)原始数据,即使我们从看起来&RefCell<T>不可变的开始。

但基本法则仍然成立。请注意,这些try_*函数返回 a Result,即它们可能会失败。如果两个函数同时尝试获取try_borrow_mut引用,则第二个函数将会失败,而您的工作就是处理这种可能性(即使“处理该情况”意味着panic!您的特定用例)。我们所做的只是将单一所有权规则从编译时移至运行时。我们还没有摆脱它们;我们刚刚改变了负责执行这些规定的人。

  • 另请注意,如果您确实使用“不安全”来“绕过”单一所有权,那么如果您只是盲目地规避规则,您的程序仍然会是错误的。‘不安全’只是意味着“我已经检查了这段代码是否遵循规则,因此编译器不必这样做”。编译器仍将假设已遵循规则,并且“不安全”块之外将在其代码生成中使用该假设。如果您在“不安全”中所做的只是规避所有权规则,则可能会导致错误的代码生成。 (2认同)