为什么这个价值不够长寿?

Obl*_*ion 5 lifetime lexical-scope rust borrowing

我不明白为什么我从这段代码中得到以下编译器错误:

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    
Run Code Online (Sandbox Code Playgroud)

编译器错误: 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
Run Code Online (Sandbox Code Playgroud)

这是我认为这段代码会逐行完成的.这些行中的一行或多行有问题,因为此代码无法编译.

 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.
Run Code Online (Sandbox Code Playgroud)

为什么编译器错误说某些东西仍然p在第13行借用?不应该hero(并且随后hero.power)掉线11号线?p在这一点上应该没有任何提及.

奇怪的是,更改值(pr)初始化的顺序可以解决问题,我不知道为什么.

修复方法:

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

在这两种情况下,简单地声明rAFTER p可以确保p在丢弃时没有任何东西仍在"借用" .这对我来说毫无意义,因为我觉得自己r没有任何关系,也没有p任何可能借用的东西p.

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

词汇生命周期的哪些属性导致这不能编译,而非词汇生命周期如何解决这个问题呢?

Jmb*_*Jmb 3

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

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

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