首页 文章

可变借款后的不变参考

提问于
浏览
5

每次使用Rust时,我都遇到与所有权/借用相关的类似问题,所以这里是最简单的一段代码,说明了我常见的问题:

use std::cell::RefCell;

struct Res {
    name: String,
}

impl Res {
    fn new(name: &str) -> Res {
        Res {
            name: name.to_string(),
        }
    }

    // I don't need all_res to be mutable
    fn normalize(&mut self, all_res: &Vec<Res>) {
        // [...] Iterate through all_res and update self.name
        self.name = "foo".to_string();
    }
}

fn main() {
    let res = RefCell::new(vec![Res::new("res1"), Res::new("res2")]);

    for r in res.borrow_mut().iter_mut() {
        // This panics at runtime saying it's
        // already borrowed (which makes sense, I guess).
        r.normalize(&*res.borrow());
    }
}

在阅读了RefCell后,我认为这样可行 . 它编译,但在运行时恐慌 .

在迭代同一向量时如何引用向量?有没有更好的数据结构允许我这样做?

1 回答

  • 6

    你的程序很恐慌,因为你试图在同一时间可变地和不可变地借用_2860878:这是不允许的 .

    你需要做的只是在 RefCell 中包装 String . 这允许您在迭代 Vec 时改变字符串 .

    use std::cell::RefCell;
    
    struct Res {
        name: RefCell<String>,
    }
    
    impl Res {
        fn new(name: &str) -> Res {
            Res {
                name: RefCell::new(name.to_string()),
            }
        }
    
        // I don't need all_res to be mutable
        fn normalize(&self, all_res: &Vec<Res>) {
            // [...] Iterate through all_res and update self.name
            *self.name.borrow_mut() = "foo".to_string();
        }
    }
    
    fn main() {
        let res = vec![Res::new("res1"), Res::new("res2")];
    
        for r in res.iter() {
            r.normalize(&res);
        }
    
        println!("{}", *res[0].name.borrow());
    }
    

相关问题