我不明白为什么我会从此代码中收到以下编译器错误:
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.
为什么编译器错误指出第13行仍在借用p
? hero
(以及随后的hero.power
)是否应该放在第11行上?此时,应该没有任何内容引用p
。
奇怪的是,更改值(p
和r
)的初始化顺序可解决此问题,我不知道为什么。
解决方法:
let p = 90;
let r;
在这两种情况下,只要在r
之后声明p
,就可以确保在丢弃p
时,什么也不会“借用”。这对我完全没有意义,因为我觉得r
与p
或可能借用p
的任何东西都没有任何关系。
此代码runs with non-lexical lifetimes enabled。
词汇生存期的哪些属性导致其无法编译,而非词汇生存期如何解决此问题?
答案 0 :(得分:3)
这只是一个猜测,但这是我想发生的情况:
Superhero
时,表示name
和power
的生存期应相同。r
的类型被推断为&String
(或者也许是&str
,关键是r
是引用)。在词法生存期中,r
必须生存到声明它的块的末尾,直到第14行。hero.name
至r
,因此hero.name
的生存期至少应与r
一样长,因此hero.name
的生存期应到第14行。 li>
hero.name
和hero.power
在每个结构声明中应具有相同的生存期,因此hero.power
也应保留到第14行。hero.power
借用了p
,因此p
的使用期限应一直到第14行,但它只存在直到声明它的块的末尾(第13行)。之所以可以使用非词汇生存期,是因为编译器注意到您在第12行之后没有使用r
,因此能够相应地缩短生存期。请注意,it doesn't work even with nll if you use r
after the closing brace of line 13。
答案 1 :(得分:1)
这是另一种解决方法。结构中'power'和'name'的生存期相同(&'a)。因此,当“电源”超出范围时,编译器会认为“名称”也超出范围。因此,您需要为您的结构定义另一个生存期