【问题标题】:Shadowing in Rust and Fighting the Borrow CheckerRust 中的阴影和与借用检查器作斗争
【发布时间】:2020-06-25 07:30:28
【问题描述】:

每次我接受用户输入时,我都会创建一个新变量(通过阴影)来获取输入。我认为这是低效的,不是阴影的目的,我还能如何有效地重用变量输入?

如果没有阴影,它会给出错误cannot borrow "input" as mutable because it is also borrowed as immutable。据我了解,接受用户输入需要可变引用。

use std::io; // Import for IO

fn main() {
    let name: &str;                 // Variables
    let balance: f32;               // Variables
    let interest: f32;              // Variables
    let mut input = String::new();  // Variables

    println!("Please enter your name: "); // Print
    io::stdin().read_line(&mut input).expect("failed to read from stdin");
    name = input.trim();
    println!("Please enter your bank account balance: "); // Print

    loop {
        let mut input = String::new(); // Remove this and I get an error
        io::stdin().read_line(&mut input).expect("failed to read from stdin");

        match input.trim().parse::<f32>() {
            Ok(_) => {
                balance = input.trim().parse().unwrap();
                break;
            },
            Err(_) => println!("Your balance cannot contain letters or symbols"),};
        }
    }

    println!("Please enter your interest rate percent: "); // Print
     
    loop {
        let mut input = String::new(); // Remove this and I get an error
        io::stdin().read_line(&mut input).expect("failed to read from stdin");
    
        match input.trim().parse::<f32>() {
            Ok(_) =>  {   
                interest = input.trim().parse().unwrap();
                break;
            },
            Err(_) => println!("Your balance cannot contain letters or symbols"),};       
        }
    }

    println!("{}, your gain from interest is : ${}", name, (interest * balance * 0.01)); // Print
}

来自 Java,我对借用如何工作以及何时使用影子是个好主意感到困惑。我了解旧值仍然存在,并且对它的任何引用都意味着如果您不再需要旧值,那么您将无缘无故地占用资源。任何建议都有帮助,谢谢。

【问题讨论】:

    标签: rust


    【解决方案1】:

    错误告诉你问题所在:

    error[E0502]: cannot borrow `input` as mutable because it is also borrowed as immutable
      --> src/main.rs:20:27
       |
    13 |     name = input.trim();
       |            ----- immutable borrow occurs here
    ...
    20 |     io::stdin().read_line(&mut input).expect("failed to read from stdin");
       |                           ^^^^^^^^^^ mutable borrow occurs here
    ...
    47 |     println!("{}, your gain from interest is : ${}", name, (interest * balance * 0.01)); //Print
       |                                                      ---- immutable borrow later used here
    

    input.trim() 创建一个对输入的不可变引用并将其存储在name 中。如果您删除了String::new() 调用,那么您调用的是io::stdin().read_line(&amp;mut input),它采用对输入的可变引用,但在name 变量中仍然存在对输入的不可变引用。

    在Rust中,不允许不可变引用和可变引用同时存在,所以编译器会报错。

    你不能在这里真正重用变量,你需要克隆或做你正在做的事情并完全创建一个新字符串。

    【讨论】:

      【解决方案2】:

      HexCoder's answer 解释说你不能在input 中重复使用String,因为它是被name 借用的。但是,要使其可重用,您只需将 input.trim() 复制到具有自己缓冲区的新 String 中:

      let name: String = input.trim().into();
      

      由于name 不再借用input,您可以擦除input 并重新使用其缓冲区。要擦除字符串,请使用String::clear

      input.clear(); // instead of `input = String::new();`
      

      Here is a more complete example 在其中我还使用模式绑定来避免解析 input 两次,并将 balanceinterest 的声明移动到可以立即初始化它们的时间。

      另见

      变量遮蔽有一些微妙之处,尤其是考虑到编译器优化时;这些问题也可能有用:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-12
        • 1970-01-01
        • 2019-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-01
        相关资源
        最近更新 更多