|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
# 认识生命周期
|
|
|
|
|
|
|
|
|
|
生命周期,简而言之就是引用的有效作用域。在大多数时候,我们无需手动的声明生命周期,因为编译器可以自动进行推导,用类型来来比下:
|
|
|
|
|
- 编译器大部分时候可以自动推导类型 <-> 编译器大多数时候也可以自动推导生明周期
|
|
|
|
|
生命周期,简而言之就是引用的有效作用域。在大多数时候,我们无需手动的声明生命周期,因为编译器可以自动进行推导,用类型来类比下:
|
|
|
|
|
- 编译器大部分时候可以自动推导类型 <-> 编译器大多数时候也可以自动推导生命周期
|
|
|
|
|
- 在多种类型存在时,编译器往往要求我们手动标明类型 <-> 当多个生命周期存在,且编译器无法推导出某个引用的生命周期时,就需要我们手动标明生命周期
|
|
|
|
|
|
|
|
|
|
Rust生命周期之所以难,是因为这个概念对于我们来说是全新,没有其它编程语言的经验可以借鉴。当你觉得难的时候,不用过于担心,这个难对于所有人都是平等的,多点付出就能早点解决此拦路虎,同时本书也会尽力帮助大家减少学习难度(生命周期很可能是Rust中最难的部分).
|
|
|
|
@ -120,7 +120,7 @@ help: consider introducing a named lifetime parameter // 考虑引入一个生
|
|
|
|
|
|
|
|
|
|
不过说来尴尬,就这个函数而言,我们也不知道返回值到底引用哪个,因为一个分支返回`x`,另一个分支返回`y`...这可咋办?先来分析下。
|
|
|
|
|
|
|
|
|
|
我们在定义该函数时,首先无法知道传递给函数的具体值,因此到底是`if`还是`else`被执行,无从得知。其次,传入引用的具体生明周期也无法知道,因此也不能像之前的例子那样通过分析生命周期来确定引用是否有效。同时,编译器的借用检查也无法推导出返回值的生命周期,因为它不知道`x`和`y`的生命周期跟返回值的生命周期之间的关系是怎样的(说实话,人都搞不清,何况编译器这个大聪明)。
|
|
|
|
|
我们在定义该函数时,首先无法知道传递给函数的具体值,因此到底是`if`还是`else`被执行,无从得知。其次,传入引用的具体生命周期也无法知道,因此也不能像之前的例子那样通过分析生命周期来确定引用是否有效。同时,编译器的借用检查也无法推导出返回值的生命周期,因为它不知道`x`和`y`的生命周期跟返回值的生命周期之间的关系是怎样的(说实话,人都搞不清,何况编译器这个大聪明)。
|
|
|
|
|
|
|
|
|
|
因此,这时就回到了文章开头说的内容:在多个引用时,编译器有时会无法自动推导生命周期,此时就需要我们手动去标注,通过为参数标注合适的生命周期来帮助编译器进行借用检查的分析。
|
|
|
|
|
|
|
|
|
@ -161,7 +161,7 @@ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
|
|
|
|
|
- 和泛型一样,使用生命周期参数,需要先声明`<'a>`
|
|
|
|
|
- `x`、`y`和返回值至少活得和`'a`一样久(因为返回值要么是`x`,要么是`y`)
|
|
|
|
|
|
|
|
|
|
该函数签名表明对于某些生命周期`'a`,函数的两个参数都至少跟`'a`活得一样久,同时函数的返回引用也至少跟`'a`活得一样久。实际上,这意味着返回值的生命周期与参数生命周期中的较小值一致:虽然两个参数的生命周期都是标注了`'a`,但是实际上这两个参数的真实生命周期可能是不一样的(生明周期`'a`不代表生命周期等于`'a`,而是大于等于`'a`)。
|
|
|
|
|
该函数签名表明对于某些生命周期`'a`,函数的两个参数都至少跟`'a`活得一样久,同时函数的返回引用也至少跟`'a`活得一样久。实际上,这意味着返回值的生命周期与参数生命周期中的较小值一致:虽然两个参数的生命周期都是标注了`'a`,但是实际上这两个参数的真实生命周期可能是不一样的(生命周期`'a`不代表生命周期等于`'a`,而是大于等于`'a`)。
|
|
|
|
|
|
|
|
|
|
回忆下“鲁迅”说的话,再参考上面的内容,可以得出:在通过函数签名指定生命周期参数时,我们并没有改变传入引用或者返回引用的真实生命周期,而是告诉编译器当不满足此约束条件时,就拒绝编译通过。
|
|
|
|
|
|
|
|
|
@ -554,7 +554,7 @@ let s: &'static str = "我没啥优点,就是活得久,嘿嘿";
|
|
|
|
|
- 实在遇到解决不了的生命周期标注问题,可以尝试`'static`,有时候它会给你奇迹
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 一个复杂例子: 泛型、特征约束、特征约束
|
|
|
|
|
## 一个复杂例子: 泛型、特征约束
|
|
|
|
|
手指已经疲软无力,我好想停止,但是华丽的开场都要有与之匹配的谢幕,那我们就用一个稍微复杂点的例子来结束:
|
|
|
|
|
```rust
|
|
|
|
|
use std::fmt::Display;
|
|
|
|
|