zl程序教程

您现在的位置是:首页 >  其他

当前栏目

Rc与RefCell

2023-04-18 15:37:34 时间

src/main.rs

#[derive(Debug)]
enum List {
    Cons(Rc<RefCell<i32>>, Rc<List>),
    Nil,
}

use crate::List::{Cons, Nil};
use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::rc::Rc;
use std::str::FromStr;
/* 
fn main() {
    // varlu是 Rc引用 指向 RefCell的地址; RefCell指向一个堆上的5
    let value = Rc::new(RefCell::new(5));
    // a 是一个Rc引用, 它指向一个Cons地址; Cons由一个指向value的Rc引用,和一个预留字段(下一个节点位置)组成;
    let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
    // b、c 是一个Cons, 它由一个Rc-RefCell和一个预留字段组成
    let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));
    let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));

    let mut b1 = *value.borrow_mut() ;// 返回RefMut;
    let mut b2 = *value.borrow_mut() ;// 返回RefMut;

    println!("a after = {:?}", a);
    println!("b after = {:?}", b);
    println!("c after = {:?}", c);
}
*/
struct MyObj {
    //1. 
    //sent_messages:Vec<String>,
    //2. 
    //sent_messages: RefCell<i32>,
    //3. 
    sent_messages: Rc<RefCell<Vec<String>>>,
    //4. 
    //sent_messages: Rc<RefCell<i32>>,
}
impl MyObj {
    fn new() -> MyObj {
        MyObj {
            //1. 
            // sent_messages:vec![],
            //2. 
            // sent_messages: RefCell::new(5),
            //3. 
            sent_messages: Rc::new(RefCell::new(vec![])),
            //4.
            //sent_messages: Rc::new(RefCell::new(5)),
        }
    }
}
fn main(){
    let myObj = MyObj::new();
    // 1. 不能编译, 违反多引用规则,提示对象未实现copy
    // let mut d1 = myObj.sent_messages;
    // let mut d2 = myObj.sent_messages;

    // 2. 不能编译, 使用RefMut存储同样不能违反多引用规则。
    // let mut d1 = myObj.sent_messages.borrow_mut();
    // let mut d2 = myObj.sent_messages.borrow_mut();

    // 错误的结论
    // 3. 可以编译, 使用Rc包装RefMut, borrow过程相当于解引用Rc,获得不可变引用,BorrowMut相当于解引用RefCell,获得可变引用
    // ------------------------------------------------------|--Rc--|----RefCell----|
    //let d1=myObj.sent_messages.borrow();
    //let mut md1 =  myObj.sent_messages.borrow().borrow_mut();
    //let mut md2 =  myObj.sent_messages.borrow().borrow_mut();
    
    //4. 能编译, 不能(*rc1).borrow_mut() 两次, 编译不通过, 提示借用多次
    let rc1 = Rc::clone(&myObj.sent_messages);
    let mut mt1 = (*rc1).borrow_mut();
    mt1.push(String::from("message"));
    // ** 小结 **
    // Rc允许多个Rc指向同一个对象, 但是不允许移动和改变对象的值(值类型除外)
    // RefCell允许在不可变引用上修改对象内部的值,但是不能移动所有权,以借用的方式修改(返回RefMut,然后调用对象的方法,在改进之前直接调用对象方法会报错)。
}