## `RefCell`和内部可变性模式 > [ch15-05-interior-mutability.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch15-05-interior-mutability.md) >
> commit 3f2a1bd8dbb19cc48b210fc4fb35c305c8d81b56 **内部可变性**(*Interior mutability*)是 Rust 中的一个设计模式,它允许你即使在有不可变引用时改变数据,这通常是借用规则所不允许。内部可变性模式涉及到在数据结构中使用`unsafe`代码来绕过 Rust 通常的可变性和借用规则。我们还未讲到不安全代码;第十九章会学习他们。内部可变性模式用于当你可以确保代码在运行时也会遵守借用规则,哪怕编译器也不能保证的情况。引入的`unsafe`代码将被封装进安全的 API 中,而外部类型仍然是不可变的。 让我们通过遵循内部可变性模式的`RefCell`类型来开始探索。 ### `RefCell`拥有内部可变性 不同于`Rc`,`RefCell`代表其数据的唯一的所有权。那么是什么让`RefCell`不同于像`Box`这样的类型呢?回忆一下第四章所学的借用规则: 1. 在任意给定时间,**只能**拥有如下中的一个: * 一个可变引用。 * 任意属性的不可变引用。 2. 引用必须总是有效的。 对于引用和`Box`,借用规则的不可变性作用于编译时。对于`RefCell`,这些不可变性作用于**运行时**。对于引用,如果违反这些规则,会得到一个编译错误。而对于`RefCell`,违反这些规则会`panic!`。 Rust 编译器执行的静态分析时天生保守的。代码的一些属性则不可能通过分析代码发现:其中最著名的就是停机问题(停机问题),这超出了本书的范畴,不过如果你感兴趣的话这是一个值得研究的有趣主题。 因为一些分析是不可能的,Rust 编译器在其不确定的时候甚至都不尝试猜测,所以说它是保守的而且有时会拒绝事实上不会违反 Rust 保证的正确的程序。换句话说,如果 Rust 接受不正确的程序,那么人们也就不会相信 Rust 所做的保证了。如果 Rust 拒绝正确的程序,会给程序员带来不变,但不会带来灾难。`RefCell`正是用于当你知道代码遵守借用规则,而编译器不能理解的时候。 类似于`Rc`,`RefCell`只能用于单线程场景。在并发章节会介绍如何在多线程程序中使用`RefCell`的功能。现在所有你需要知道的就是如果尝试在多线程上下文中使用`RefCell`,会得到一个编译错误。 对于引用,可以使用`&`和`&mut`语法来分别创建不可变和可变的引用。不过对于`RefCell`,我们使用`borrow`和`borrow_mut`方法,它是`RefCell`拥有的安全 API 的一部分。`borrow`返回`Ref`类型的智能指针,而`borrow_mut`返回`RefMut`类型的智能指针。这两个类型实现了`Deref`所以可以被当作常规引用处理。`Ref`和`RefMut`动态的借用所有权,而他们的`Drop`实现也动态的释放借用。