将表达式赋值给变量VS只是将变量内联到另一个表达式之间有什么区别?

时间:2017-04-29 10:14:22

标签: rust borrow-checker

我在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

我相信我遗漏了与借阅检查程序相关的内容,但甚至无法理解它可能是什么,因为我预计一个甚至不能直接分配的临时值与借用没有任何关系?!

1 个答案:

答案 0 :(得分:3)

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

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

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

在您的情况下,有两种可能性

  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());