Rust 中的不可变和可变借用

问题描述 投票:0回答:1

我正在尝试开发一个 Rust 应用程序。由于对 Rust 相当陌生,我发现借用检查器很难使用。下面是我从更大的代码库中分离出来的 MRE,但它具体说明了我的问题。在

do_something
内,该行被注释掉(标记为 2)),程序可以正常编译并按预期工作,但是当该行被注释掉(标记为 1))时,它会失败,并显示错误消息。

我意识到问题是由于内存安全造成的,并且编译器试图确保没有任何内容会意外改变......但是我无法理解第 1) 行和第 2) 行之间确切的根本区别是什么;据我所知,它们是相同的。

我也一直在拼命寻找一种通用的方法来解决问题。我之前在同一个代码库中用几个

clone
解决了一个非常相似的问题。在这种情况下,克隆 v(我怀疑这是问题的根源?)并不能解决问题。

#[derive(Debug, Default)]
struct MyStruct {
    my_idx: usize,
    my_vals: Vec<String>,
    my_log: Vec<String>,
}
impl MyStruct {
    pub fn new() -> Self { Self::default() }

    // Push a message to the log-vector.
    pub fn push_msg(&mut self, msg: String) {
        let tmp = self.fmt_msg(msg);
        self.my_log.push(tmp);
    }

    // Format a message and return a String
    pub fn fmt_msg(&self, msg: String) -> String { format!("msg is: {}", msg) }

    // Get a value from my_vals. Create a log message, two ways.
    pub fn do_something(&mut self) -> String {
        let ret_val = match self.my_vals.get(self.my_idx) {
            Some(v) => {
                let msg = self.fmt_msg(format!("Some {}", v));
                self.push_msg(msg);        // 1) This line doesn't work
                // self.my_log.push(msg);  // 2) This line works
                format!("Some {:?}", v)
            },
            None => format!("None")
        };
        ret_val
    }
}


fn main() {
    let mut ms = MyStruct::new();           // Init struct
    ms.my_vals.push(String::from("aa"));    // Push some value to the struct
    ms.push_msg(String::from("bcd"));       // Test push_msg-function, works as a stand-alone call
    ms.do_something();                      // Test function
    println!("Main, after: {:?}", ms);      // Just check the state of the struct after
}

在MRE中使用1)时出现如下错误信息:

PS C:\Users\rust_stuff\borrow_test> cargo run
   Compiling borrow_test v0.1.0 (C:\Users\rust_stuff\borrow_test)
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
  --> src\main.rs:24:17
   |
21 |         let ret_val = match self.my_vals.get(self.my_idx) {
   |                             ------------ immutable borrow occurs here
...
24 |                 self.push_msg(msg);        // 1) This line doesn't work
   |                 ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
25 |                 // self.my_log.push(msg);  // 2) This line works
26 |                 format!("Some {:?}", v)
   |                                      - immutable borrow later used here

For more information about this error, try `rustc --explain E0502`.
error: could not compile `borrow_test` (bin "borrow_test") due to previous error

Stack Overflow 上已经有几个非常相似的问题了,但我还没有设法将这些答案转换为我的具体案例。在其他答案中,我发现这个问题最相似。

rust borrow-checker
1个回答
0
投票

错误信息显示,从

match
语句开始,
v
中获取的
Some(v)
引用仍然在使用,直到这个
match
臂结束(产生返回值),而变异操作
.push_msg()
借用了
self
作为一个整体。 但
v
指的是
self
的一部分;借用检查器禁止这种情况。

一种解决方法是在变异操作.push_msg()之前

准备结果,以便在此变异之后不再使用参考
v

pub fn do_something(&mut self) -> String { let ret_val = match self.my_vals.get(self.my_idx) { Some(v) => { let result = format!("Some {:?}", v); let msg = self.fmt_msg(format!("Some {}", v)); self.push_msg(msg); result } None => format!("None"), }; ret_val }
    
© www.soinside.com 2019 - 2024. All rights reserved.