5

我不明白为什么我会从此代码中收到以下编译器错误:

struct Superhero<'a> { name: &'a String, power: &'a i32 } //  1    
                                                          //  2    
fn main() {                                               //  3    
    let n = "Bruce Wayne".to_string();                    //  4    
    let r;                                                //  5    
    {                                                     //  6    
        let p = 98;                                       //  7    
        {                                                 //  8    
            let hero = Superhero{ name: &n, power: &p };  //  9    
            r = hero.name;                                // 10    
        }                                                 // 11    
        println!("{}", r);                                // 12    
    }                                                     // 13    
}                                                         // 14    

编译器错误:rustc 1.27.1 (5f2b325f6 2018-07-07)

error[E0597]: `p` does not live long enough
  --> src/main.rs:9:53
   |
9  |             let hero = Superhero{ name: &n, power: &p };
   |                                                     ^ borrowed value does not live long enough
...
13 |     }
   |     - `p` dropped here while still borrowed
14 | }
   | - borrowed value needs to live until here

这是我认为这段代码会做的事情,一行一行。这些行中的一行或多行有问题,因为此代码无法编译。

 4: Initialize name: String to "Bruce Wayne".to_string();
 5: Declare r to be initialized in a different scope
 6: Begin a new scope (A)
 7: Initialize p to 98
 8: Begin a new scope (B)
 9: Initialize hero: Superhero to a new struct
       hero.name refers to the variable{n},
       hero.power refers to the variable{p}  
10: Copy a reference to the variable{n}, 
       since reference types are copy, both hero.name and r are distinct references to the variable{n}.
11: End scope (B): hero and the two references it owns {hero.name, hero.power} are dropped.
12: Print the value of the variable{r}: Should print "Bruce Wayne"
13: End scope (A): the variable{p} is dropped.
14: End scope for main. The variables {n, r} are dropped.

为什么编译器错误说p第 13 行仍有一些东西在借用?不应该hero(以及随后hero.power)在第 11 行被删除吗?p在这一点上应该没有什么可提及的。

p奇怪的是,更改值 (和) 的初始化顺序r解决了这个问题,我不知道为什么。

修复方法:

  1. let p = 90;在第 4 行和第 5 行之间移动第 7行
  2. let r;在第 7 行和第 8 行之间移动第 5行

在这两种情况下,简单地声明rAFTERp可以确保p在删除时没有任何东西仍然“借用”。这对我来说根本没有意义,因为我觉得与或任何可能借用的东西r毫无关系。 pp

此代码在启用非词法生命周期的情况下运行

词法生命周期的什么属性导致它无法编译,非词法生命周期如何解决这个问题?

4

2 回答 2

3

这只是一个猜测,但这是我认为会发生的情况:

  • 当您声明 时Superhero,您声明了name并且power应该具有相同的生命周期。
  • for 的类型r被推断为&String(或者可能&str,重点是r引用)。对于词法生命周期,r它必须一直存在到声明它的块的末尾,所以直到第 14 行。
  • 既然你影响hero.namerhero.name至少应该活到r,因此hero.name应该活到第 14 行。
  • 因为hero.name并且hero.power每个结构声明都应该具有相同的生命周期,所以hero.power也应该活到第 14 行。
  • 由于hero.powerborrows pp应该一直存在到第 14 行,但它只存在到声明它的块的末尾(第 13 行)。

它适用于非词法生命周期的原因是因为编译器注意到您r在第 12 行之后不再使用,因此能够相应地缩短生命周期。请注意,如果您在第 13 行的右括号之后使用它,即使使用 nll 也不起作用r

于 2018-07-12T06:37:26.760 回答
1

https://play.rust-lang.org/?gist=48362cfc5ee81ff07628f9b60477c4cb&version=nightly&mode=debug&edition=2015

这是另一种解决方法。结构中“power”和“name”的生命周期是相同的(&'a)。所以当'power'超出范围时,编译器会认为'name'也超出范围。所以你需要为你的结构定义另一个生命周期

于 2018-07-12T05:35:23.133 回答