将表达式分配给变量与仅将变量内联到另一个表达式之间有什么区别?

What is the difference between assigning an expression to a variable VS just inlining the variable into another expression?

我在 Rust 中有以下代码:

fn send_message(_: &[u8]) {}

let args: Vec<String> = std::env::args().collect();
let string_message = args[1..].join(" ") + "\nEND\n";
let socket_message = string_message.as_bytes();

send_message(&socket_message);

这行得通。但是,我想避免在那里使用 string_message 变量,所以我只是在 socket_message:

的声明中内联该表达式
let args: Vec<String> = env::args().collect();
let socket_message = (args[1..].join(" ") + "\nEND\n").as_bytes();

send_message(&socket_message);

不过,Rust 并不认为这两个片段是相同的!

它给出了这个错误:

error: borrowed value does not live long enough
  --> <anon>:7:70
   |
7  |     let socket_message = (args[1..].join(" ") + "\nEND\n").as_bytes();
   |                          ---------------------------------           ^ temporary value dropped here while still borrowed
   |                          |
   |                          temporary value created here
...
10 | }
   | - temporary value needs to live until here
   |
   = note: consider using a `let` binding to increase its lifetime

我相信我遗漏了一些与借用检查器相关的东西,但我什至不明白它可能是什么,因为我期望一个甚至没有直接分配的临时值与借用没有任何关系?!

正如编译器告诉你的那样:

= note: consider using a `let` binding to increase its lifetime

... let 绑定可以增加值的生命周期。您的表达式 args[1..].join(" ") + "\nEND\n" 创建了一个 String 类型的值。在语句中创建的值不会超过该语句,除非它们被命名(使用 let 绑定)或被 rvalue promoted。后一种情况在这里不适用,因为你没有命名你的价值,它不会比父声明长寿。通常,这并不是真正的问题,但是如果你想稍后 reference 表示值,你将引用一些死的东西。因此借阅检查员的抱怨。

你的情况,有两种可能:

  1. 足够的内联表达式,这样您就不会在语句之外引用值:

    let args: Vec<String> = env::args().collect();
    send_message(&(args[1..].join(" ") + "\nEND\n").as_bytes());
    

    如您所见:我们的语句中仍然有临时字符串,但没关系,因为我们只在该语句中引用它。

  2. 使用 let 绑定来增加值的生命周期,就像您在第一个示例中所做的那样。您仍然可以像这样将代码缩短一行:

    let args: Vec<String> = env::args().collect();
    let string_message = args[1..].join(" ") + "\nEND\n";
    
    send_message(string_message.as_bytes());