同一函数中出现“does not live long enough”错误

6
我原本以为这段代码可以正常工作,因为所有绑定都在同一个作用域中:
fn main() {
    let mut foobar = vec!["foo"];
    let bar = "bar".to_string();
    foobar.push(&bar);
}

但我遇到了这个错误:
error: `bar` does not live long enough
 --> baz.rs:4:18
  |>
4 |>     foobar.push(&bar);
  |>                  ^^^
note: reference must be valid for the block suffix following statement 0 at 2:33...
 --> baz.rs:2:34
  |>
2 |>     let mut foobar = vec!["foo"];
  |>                                  ^
note: ...but borrowed value is only valid for the block suffix following statement 1 at 3:32
 --> baz.rs:3:33
  |>
3 |>     let bar = "bar".to_string();
  |>                                 ^

error: aborting due to previous error
1个回答

10

在同一块中声明的变量按照它们声明的相反顺序被删除。在你的代码中,barfoobar 之前被删除:

fn main() {
    let mut foobar = vec!["foo"]; // <---------| 0
    let bar = "bar".to_string();  // <--| 1    |
    foobar.push(&bar);            //    | bar  | foobar
                                  // <--|      |
                                  // <---------|
    // In the error message
    // 0 is called "block suffix following statement 0", and
    // 1 is called "block suffix following statement 1"
}
你正在将对`bar`的引用推入`foobar`中,因此你必须确保`bar`的生命期至少与`foobar`一样长。但是由于`bar`在`foobar`之后声明,所以`bar`的生命周期实际上比`foobar`短,这意味着`foobar`短暂地包含了一个悬空引用。
为了使代码编译通过,在`foobar`之前声明`bar`。
fn main() {
    let bar = "bar".to_string();
    let mut foobar = vec!["foo"];
    foobar.push(&bar);
}

或选择使用非词法生命周期

#![feature(nll)]

fn main() {
    let mut foobar = vec!["foo"];
    let bar = "bar".to_string();
    foobar.push(&bar);
}
尽管它仍然有一个悬空的引用,但这并不重要,因为放弃引用不会对任何事情产生影响;当 Vec 被丢弃时,它不需要使用它所包含的引用的值。

对于其他遇到此问题的人,我建议阅读https://aochagavia.github.io/blog/exploring-rusts-unspecified-drop-order/。 - hannu40k

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