@ -381,12 +381,12 @@ fn first_word<'a>(s: &'a str) -> &'a str {
例如函数 `fn foo(x: &i32) -> &i32` , `x` 参数的生命周期会被自动赋给返回值 `&i32` ,因此该函数等同于 `fn foo<'a>(x: &'a i32) -> &'a i32`
例如函数 `fn foo(x: &i32) -> &i32` , `x` 参数的生命周期会被自动赋给返回值 `&i32` ,因此该函数等同于 `fn foo<'a>(x: &'a i32) -> &'a i32`
3. ** 若存在多个输入生命周期,且其中一个是 `&self` 或 `&mut self` ,则 `&self` 的生命周期被赋给所有的输出生命周期**
3. ** 若存在多个输入生命周期,且其中一个是 `&self` 或 `&mut self` ,则 `&self` 或 `&mut self` 的生命周期被赋给所有的输出生命周期**
拥有 `&self` 形式的参数,说明该函数是一个 `方法` ,该规则让方法的使用便利度大幅提升。
拥有 `&self` 或 `&mut self` 形式的参数,说明该函数是一个 `方法` ,该规则让方法的使用便利度大幅提升。
规则其实很好理解,但是,爱思考的读者肯定要发问了,例如第三条规则,若一个方法,它的返回值的生命周期就是跟参数 `&self` 的不一样怎么办?总不能强迫我返回的值总是和 `& self` 活得一样久吧?! 问得好,答案很简单:手动标注生命周期,因为这些规则只是编译器发现你没有标注生命周期时默认去使用的,当你标注生命周期后,编译器自然会乖乖听你的话。
规则其实很好理解,但是,爱思考的读者肯定要发问了,例如第三条规则,若一个方法,它的返回值的生命周期就是跟参数 `&self` 或 `&mut self` 的不一样怎么办?总不能强迫我返回的值总是和 `& self` 或 `&mut self` 活得一样久吧?! 问得好,答案很简单:手动标注生命周期,因为这些规则只是编译器发现你没有标注生命周期时默认去使用的,当你标注生命周期后,编译器自然会乖乖听你的话。
让我们假装自己是编译器,然后看下以下的函数该如何应用这些规则:
让我们假装自己是编译器,然后看下以下的函数该如何应用这些规则:
@ -519,7 +519,7 @@ impl<'a> ImportantExcerpt<'a> {
此时,编译器会报错,因为编译器无法知道 `'a` 和 `'b` 的关系。 `&self` 生命周期是 `'a` ,那么 `self.part` 的生命周期也是 `'a` ,但是好巧不巧的是,我们手动为返回值 `self.part` 标注了生命周期 `'b` ,因此编译器需要知道 `'a` 和 `'b` 的关系。
此时,编译器会报错,因为编译器无法知道 `'a` 和 `'b` 的关系。 `&self` 生命周期是 `'a` ,那么 `self.part` 的生命周期也是 `'a` ,但是好巧不巧的是,我们手动为返回值 `self.part` 标注了生命周期 `'b` ,因此编译器需要知道 `'a` 和 `'b` 的关系。
有一点很容易推理出来:由于 `&'a self` 是被引用的一方,因此引用它的 `&'b str` 必须要活得比它短,否则会出现悬垂引用。因此说明生命周期 `'b` 必须要比 `'a` 小 ,只要满足了这一点,编译器就不会再报错:
有一点很容易推理出来:由于 `&'a self` 是被引用的一方,因此引用它的 `&'b str` 必须活在它(`& 'a self`)被丢弃前,否则会出现悬垂引用。因此说明生命周期 `'b` 必须要活在 `'a` 死之前 ,只要满足了这一点,编译器就不会再报错:
```rust
```rust
impl< 'a: 'b, 'b> ImportantExcerpt< 'a> {
impl< 'a: 'b, 'b> ImportantExcerpt< 'a> {
fn announce_and_return_part(& 'a self, announcement: & 'b str) -> & 'b str {
fn announce_and_return_part(& 'a self, announcement: & 'b str) -> & 'b str {