Z
ZHANK
编程在线教程Rust 教程RefCell 内部可变性
智能指针

RefCell 内部可变性

RefCell<T> 运行时借用检查、borrow/borrow_mut、Rc<RefCell<T>> 模式

RefCell 内部可变性

RefCell<T> 把借用检查推迟到运行时——即使外部是不可变引用,内部也可以修改。经典组合:Rc<RefCell<T>>

学完本章你将: 掌握 RefCell borrow/borrow_mut、运行时检查、Rc<RefCell> 模式。


RefCell 基础

rust
use std::cell::RefCell;

fn main() {
    let data = RefCell::new(42);

    // 不可变借用(运行时检查)
    {
        let borrowed = data.borrow();
        println!("{}", *borrowed);  // 42
    }  // borrow 离开作用域——归还

    // 可变借用
    {
        let mut borrowed = data.borrow_mut();
        *borrowed = 100;
    }

    println!("{}", data.borrow());  // 100
}

Rc> —— 共享可变数据

rust
use std::rc::Rc;
use std::cell::RefCell;

#[derive(Debug)]
struct Node {
    value: i32,
    children: RefCell<Vec<Rc<Node>>>,
}

fn main() {
    let leaf = Rc::new(Node {
        value: 3,
        children: RefCell::new(vec![]),
    });

    let branch = Rc::new(Node {
        value: 5,
        children: RefCell::new(vec![Rc::clone(&leaf)]),
    });

    // 即使 branch 是 Rc(不可变引用),也能修改 children
    branch.children.borrow_mut().push(Rc::new(Node {
        value: 7,
        children: RefCell::new(vec![]),
    }));
}

运行时借用规则

rust
let data = RefCell::new(42);

let r1 = data.borrow();
// let r2 = data.borrow_mut();  // ❌ panic——已有不可变借用
drop(r1);

let mut r2 = data.borrow_mut();
// let r3 = data.borrow();       // ❌ panic——已有可变借用

⚠️ RefCell 在运行时检查规则——违反会 panic。编译器不会阻止你写出有问题的代码。