如何操作Rust env::args并避免“borrowed时临时值已删除”的问题?

4

我不知道如何按照编译器的建议进行操作:考虑使用let绑定来创建寿命更长的值

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
1个回答

9
#![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

#![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()


1
你甚至可以将字符串声明为 let string;这样 string 就不需要是可变的,编译器足够聪明,可以确定它在所有使用它的代码路径中都被正确初始化。 - user4815162342
@user4815162342,明白了。已经做出了更改。 - Mihir Luthra
这对于匹配块来说已经足够了,但是对于for循环呢,其中string的值会在每次迭代中改变呢? - theberzi
@MihirLuthra 我的使用情况涉及在循环中使用 format!。 (https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2d76eee0e2cc109752264bedd178f92c) - theberzi
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接