可变借用后的不可变引用 [英] Immutable reference after mutable borrow

查看:37
本文介绍了可变借用后的不可变引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I run into similar problems related to ownership/borrowing every time I use Rust, so here is the simplest piece of code that illustrates my usual problems:

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 我认为这会奏效.它可以编译,但在运行时会发生恐慌.

After reading about RefCell I thought this would work. It compiles, but panics at runtime.

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

How do I reference a vector while iterating over the same vector? Is there any better data structure to allow me to do this?

推荐答案

您的程序出现混乱,因为您试图同时可变且不可变地借用 Vec:这是不允许的.

Your program panics because you're trying to borrow the Vec mutably and immutably at the same time: this is not allowed.

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

What you need to do instead is wrap only the Strings in RefCell. This allows you to mutate the strings while iterating the 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());
}

这篇关于可变借用后的不可变引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆