大家好,我是砸锅。一个摸鱼八年的后端开发。熟悉 Go、Lua。第十九天还是继续和大家一起学习 Rust😊
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情
生命周期
静态生命周期
在 Rust 中,除非显式做 Box::leak() / Box::into_raw() / ManualDrop 等这些操作,否则一般来说,堆内存的生命周期,都是默认和其栈内存的生命周期绑定在一起
如果一个值的生命周期贯穿这个进程的生命周期,那么这种生命周期就称为静态生命周期。例如全局变量、静态变量、字符串字面量等都拥有静态生命周期。在值拥有静态生命周期的时候,表述静态引用时,可以用 ‘static 来表示,例如 &’static str
动态生命周期
如果一个值是在某个作用域里面定义的,那就是它被创建在栈上或者是堆上,其生命周期是动态的
值的作用域结束时,这个值的生命周期也会结束。对于动态生命周期,可以用 ‘a、’b 这样的小写字符或者字符串来表述,’ 后面的名字不重要
全局变量、静态变量、字符串字面量、代码等在编译时会放在可执行文件的 BSS / Data / RoData / Text 段里面,然后加载的时候装入内存。所以它们的生命周期和进程的生命周期一样,是静态的
函数指针也是静态的,因为函数在 Text 段中,进程存在,其内存也一直存在
分配在堆和栈上的内存都有各自的作用域,所以它们的生命周期都是动态的
编译器如何识别生命周期
因为编译器判断生命周期的信息,就是函数本身携带的信息。所以如果不在函数签名里提供生命周期的信息,编译器就很难确定多个参数的生命周期
为什么有些代码的函数参数和返回值都有用到引用,编译器却不提示错误呢?是因为编译器自动加了生命周期标注,其实所有使用引用的函数都需要加上生命周期的标注,如果满足这些简单的规则,编译器就会自动加上生命周期标注:
- 所有引用类型的参数都有独立的生命周期 ‘a、’b 等
- 如果只有一个引用输入,它的生命周期会赋给所有输出
- 如果有多个引用类型的参数,其中一个为 self,那么它的生命周期会赋予所有输出
因此需要函数签名里提供,也就是生命周期标注 (lifetime specifier) ,生命周期标注时,使用的参数叫生命周期参数 (lifetime parameter) 。通过生命周期标注告诉编译器这些引用的生命周期约束
生命周期参数描述的方式和泛型参数一致,不过只使用小写字母。注意的是,生命周期参数,描述的是参数和参数之间、参数和返回值之间的关系,不会改变原有的生命周期
fn max<'a>(s1: &'a str, s2: &'a str) -> &'a str {}
使用数据结构时,数据结构本身的生命周期,需要小于等于其内部字段的所有引用的生命周期