【问题标题】:How can you manipulate Rust env::args and avoid "temporary value dropped while borrowed"?借入时临时价值下降
【发布时间】:2021-03-05 05:02:26
【问题描述】:

我不知道如何遵循编译器的建议:consider using a let binding to create a longer lived value

Playground

#![allow(unused)]
fn main() {
let a_dir=std::env::args().nth(2);
    
    let  dir:&str=match a_dir{
      Some (ref a)=> &format!("./{}/**/*.liquid",a) as &str,
      None=>{"./**/*.liquid"},
    };
}
error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:6:23
  |
5 |     let  dir:&str=match a_dir{
  |          --- borrow later stored here
6 |       Some (ref a)=> &format!("./{}/**/*.liquid",a) as &str,
  |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^       - temporary value is freed at the end of this statement
  |                       |
  |                       creates a temporary which is freed while still in use
  |
  = note: consider using a `let` binding to create a longer lived value

【问题讨论】:

    标签: rust


    【解决方案1】:
    #![allow(unused)]
    fn main() {
        let a_dir = std::env::args().nth(2);
    
        let dir: &str = match a_dir {
            Some(ref a) => &format!("./{}/**/*.liquid", a) as &str,
            None => "./**/*.liquid",
        };
    }
    

    在您的代码中,在 Some 匹配的情况下,您正在创建一个拥有的 String。哪个在匹配块的末尾被丢弃。

    format!("./{}/**/*.liquid", a);
    

    这会产生一个String,然后你返回一个对它的引用。

    但在匹配块的末尾,format!() 生成的 String 实际上已经下降,因此您试图返回一个悬空引用,因为编译器拒绝了您的代码。


    “考虑使用 let 绑定来创建更长寿的值”

    简单来说,编译器建议您在之前创建 String 并将其存储在某处,这样它就不会被丢弃并且您能够返回一个有效的引用。

    按照编译器的建议进行:

    #![allow(unused)]
    fn main() {
        let a_dir = std::env::args().nth(2);
    
        let string;
        let dir: &str = match a_dir {
            Some(ref a) => {
                string = format!("./{}/**/*.liquid", a);
                &string
            },
            None => "./**/*.liquid",
        };
    }
    

    这将创建一个名为string 的变量,该变量将存在足够长的时间,并且您将从format!() 生成的String 存储在string 中。然后返回对string 的引用。

    虽然更好的方法是在这里使用String

    #![allow(unused)]
    fn main() {
        let a_dir = std::env::args().nth(2);
        
        let dir = a_dir
            .as_ref()
            .map(|val| format!("./{}/**/*.liquid", val))
            .unwrap_or_else(|| "./**/*.liquid".to_string());
    }
    

    如果您想要&str,您可以直接使用dir.as_str()

    【讨论】:

    • 你甚至可以将字符串声明为let string;这样string 不需要是可变的,并且编译器足够聪明,可以确定它在所有使用它的代码路径中都正确初始化。
    • @user4815162342,有道理。做出改变。
    • 这对于一个匹配块来说已经足够好了,但是对于一个 for 循环呢,string 的值会在每次迭代中改变?
    • @theberzi 我不完全理解你的意思,但对我来说大致相同:play.rust-lang.org/…
    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    相关资源
    最近更新 更多