将 `Ref` 改为 `Ref<T>`

pull/418/head
wtklbm 4 years ago
parent a33883cb55
commit 4d3e694894

@ -55,7 +55,7 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable
| ^ cannot borrow mutably | ^ cannot borrow mutably
``` ```
然而,特定情况下在值的方法内部能够修改自身是很有用的,而不是在其他代码中。此时值仍然是不可变的,值方法外部的代码不能修改其值。`RefCell<T>` 是一个获得内部可变性的方法。`RefCell<T>` 并没有完全绕开借用规则,编译器中的借用检查器允许内部可变性并相应地在运行时检查借用规则。如果违反了这些规则,会得到 `panic!` 而不是编译错误。 然而,特定情况下在值的方法内部能够修改自身是很有用的,而不是在其他代码中。此时值仍然是不可变的,值方法外部的代码不能修改其值。`RefCell<T>` 是一个获得内部可变性的方法。`RefCell<T>` 并没有完全绕开借用规则,编译器中的借用检查器允许内部可变性并相应地在运行时检查借用规则。如果违反了这些规则,会出现 panic 而不是编译错误。
让我们通过一个实际的例子来探索何处可以使用 `RefCell<T>` 来修改不可变值并看看为何这么做是有意义的。 让我们通过一个实际的例子来探索何处可以使用 `RefCell<T>` 来修改不可变值并看看为何这么做是有意义的。
@ -255,9 +255,9 @@ mod tests {
### `RefCell<T>` 在运行时记录借用 ### `RefCell<T>` 在运行时记录借用
当创建不可变和可变引用时,我们分别使用 `&``&mut` 语法。对于 `RefCell<T>` 来说,则是 `borrow``borrow_mut` 方法,这属于 `RefCell<T>` 安全 API 的一部分。`borrow` 方法返回 `Ref` 类型的智能指针,`borrow_mut` 方法返回 `RefMut` 类型的智能指针。这两个类型都实现了 `Deref`,所以可以当作常规引用对待。 当创建不可变和可变引用时,我们分别使用 `&``&mut` 语法。对于 `RefCell<T>` 来说,则是 `borrow``borrow_mut` 方法,这属于 `RefCell<T>` 安全 API 的一部分。`borrow` 方法返回 `Ref<T>` 类型的智能指针,`borrow_mut` 方法返回 `RefMut` 类型的智能指针。这两个类型都实现了 `Deref`,所以可以当作常规引用对待。
`RefCell<T>` 记录当前有多少个活动的 `Ref<T>``RefMut<T>` 智能指针。每次调用 `borrow``RefCell<T>` 将活动的不可变借用计数加一。当 `Ref` 值离开作用域时,不可变借用计数减一。就像编译时借用规则一样,`RefCell<T>` 在任何时候只允许有多个不可变借用或一个可变借用。 `RefCell<T>` 记录当前有多少个活动的 `Ref<T>``RefMut<T>` 智能指针。每次调用 `borrow``RefCell<T>` 将活动的不可变借用计数加一。当 `Ref<T>` 值离开作用域时,不可变借用计数减一。就像编译时借用规则一样,`RefCell<T>` 在任何时候只允许有多个不可变借用或一个可变借用。
如果我们尝试违反这些规则,相比引用时的编译时错误,`RefCell<T>` 的实现会在运行时出现 panic。示例 15-23 展示了对示例 15-22 中 `send` 实现的修改,这里我们故意尝试在相同作用域创建两个可变借用以便演示 `RefCell<T>` 不允许我们在运行时这么做: 如果我们尝试违反这些规则,相比引用时的编译时错误,`RefCell<T>` 的实现会在运行时出现 panic。示例 15-23 展示了对示例 15-22 中 `send` 实现的修改,这里我们故意尝试在相同作用域创建两个可变借用以便演示 `RefCell<T>` 不允许我们在运行时这么做:

Loading…
Cancel
Save