为什么这个值活得不够长?
Why does this value not live long enough?
我不明白为什么我会从这段代码中得到以下编译器错误:
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
?不应该在第 11 行删除 hero
(以及随后的 hero.power
)吗?此时应该没有任何内容涉及 p
。
奇怪的是,更改值(p
和 r
)的初始化顺序解决了这个问题,我不知道为什么。
修复方法:
- 将第 7 行
let p = 90;
移动到第 4 行和第 5 行之间
- 将第 5 行
let r;
移动到第 7 行和第 8 行之间
在这两种情况下,只需在 p
之后声明 r
即可确保在删除时没有任何内容仍然是 "borrowing" p
。这对我来说毫无意义,因为我觉得 r
与 p
或任何可能借用 p
的东西完全没有关系。
此代码runs with non-lexical lifetimes enabled.
什么 属性 词法生命周期导致无法编译,非词法生命周期如何解决这个问题?
这是另一种修复方法。结构中 'power' 和 'name' 的生命周期相同 (&'a)。所以当 'power' 超出范围时,编译器会认为 'name' 也超出范围。所以你需要为你的结构定义另一个生命周期
这只是一个猜测,但这是我认为会发生的情况:
- 当您声明
Superhero
时,您声明 name
和 power
应该具有相同的生命周期。
r
的类型被推断为 &String
(或者可能是 &str
,关键是 r
是一个引用)。对于词法生命周期,r
必须一直存在到声明它的块的末尾,因此直到第 14 行。
- 因为你影响
hero.name
到 r
,hero.name
应该至少和 r
一样长,因此 hero.name
应该活到第 14 行。
- 由于
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.
我不明白为什么我会从这段代码中得到以下编译器错误:
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
?不应该在第 11 行删除 hero
(以及随后的 hero.power
)吗?此时应该没有任何内容涉及 p
。
奇怪的是,更改值(p
和 r
)的初始化顺序解决了这个问题,我不知道为什么。
修复方法:
- 将第 7 行
let p = 90;
移动到第 4 行和第 5 行之间 - 将第 5 行
let r;
移动到第 7 行和第 8 行之间
在这两种情况下,只需在 p
之后声明 r
即可确保在删除时没有任何内容仍然是 "borrowing" p
。这对我来说毫无意义,因为我觉得 r
与 p
或任何可能借用 p
的东西完全没有关系。
此代码runs with non-lexical lifetimes enabled.
什么 属性 词法生命周期导致无法编译,非词法生命周期如何解决这个问题?
这是另一种修复方法。结构中 'power' 和 'name' 的生命周期相同 (&'a)。所以当 'power' 超出范围时,编译器会认为 'name' 也超出范围。所以你需要为你的结构定义另一个生命周期
这只是一个猜测,但这是我认为会发生的情况:
- 当您声明
Superhero
时,您声明name
和power
应该具有相同的生命周期。 r
的类型被推断为&String
(或者可能是&str
,关键是r
是一个引用)。对于词法生命周期,r
必须一直存在到声明它的块的末尾,因此直到第 14 行。- 因为你影响
hero.name
到r
,hero.name
应该至少和r
一样长,因此hero.name
应该活到第 14 行。 - 由于
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.