在Rust中隐藏阴影并与借入检查器对抗

时间:2019-07-19 03:04:56

标签: rust

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

在没有阴影的情况下,它会给出错误“无法借用“输入”为可变的,因为它也被借为不可变的。据我所知,接受用户输入需要可变的引用。

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,我对借用如何工作以及何时进行阴影感到困惑。我知道旧值仍然存在,并且对其进行任何引用,这意味着如果您不再需要旧值,那么您将无缘无故地占用资源。任何建议都是有帮助的,谢谢。

2 个答案:

答案 0 :(得分:2)

该错误告诉您问题所在:

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(&mut input),它使用可变的输入引用,但是name变量中仍然有不可变的输入引用。

在Rust中,不允许同时存在不可变引用和可变引用,因此编译器会出错。

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

答案 1 :(得分:2)

HexCoder's answer解释说您无法重用String中的input,因为它是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的声明移到可以立即初始化的位置。 / p>

另请参见

变量阴影有一些细微之处,尤其是在考虑编译器优化的情况下;这些问题也可能有用: