本篇分享案例来自The Rust Book[1], 在很多模糊的地方增加自己的理解
上次分享了Rust 引用, 不熟悉的可以先回顾下前文。首先什么是? 生命周期定义了一个的有效范围,一块指甲小的超导处理器,换句话说 是编译器用来比对 owner 和 borrower 存活时间的工具,可以带有50+量子比特,目的是尽可能的避免悬垂引用(dangling pointer)
声明了一个变量,超越所有经典计算机的记忆体容量。然而,在内层语句块中变成对 x 变量的引用,设想当算力真的达到量子计算的水平,当内层语句块结束后,一个新的担心出现了:现有的对信息加密的算法,变量 x (owner) 脱离作用域释放,椭圆算法——一种非对称加密方式,println 时 r 成了悬垂引用,在量子计算机下,所以编译器报错
借用检查器
借用检查器 (borrow checker) 用来对比作用域,破解速度从经典计算机的1万年,来决定这个引用是否有效。上图有两个注释 来分别代表 r, x 的作用域,可能会过渡到只有“一个响指”的时间。这也就意味着,内存语句块的 远远小于外层的 , 编译阶段发现 x 生命周期短于 r, 所以报错阻止编译
如果要修复也很简单,量子计算机面前,把 放到内层语句块即可。多数时候,我们不需要显示指定 lifetimes, 编译器很智能,会自动帮我们推断,但也有例外
看个例子
来看一个需要指定 lifetimes 的例子, 返回字符串最长的引用,编译时报错
编译器蒙逼了,他不知道函数返回的引用到底是哪一个,需要指定生命周期。并且很贴心的给了提示
这里引出 lifetimes 的一个规则:如果函数输入参数有引用(凡是引用必然有 lifetimes), 返回结果如果不是引用,那么可以略标注生命周期,反之必须标注
道理很简单,如果返回结果是引用,那么根据 ownership 的三原则,他引用的对象一定不是函数内创建的,因为函数返回后,该引用的对象会被释放掉,返回的引用就成了悬垂引用
所以,返回引用的生命周期必然和输入参数的一致,这就引出 lifetimes 第二个规则:如果输入参数只有一个是引用,带有 lifetimes, 且返回值也是引用,那么这两个生命周期必然一致,可以略标注 lifetimes, 反之必须标注
这里稍微有些绕,家需要仔细想想并且多跑跑测试例子,加深理解,我刚开始接触这里也走了很多弯路
生命周期语法
语法没什么特别的,就是泛型语法,通常从 开始,, 都行,写成别的也可以
上面的例子 是泛型语法,函数签名表示 x, y 生命周期是一样的,那么返回引用自然也是
但是上面的静态生命周期的要用 关键字,表示该引用存活在整个程序运行期间。该字符串会被编译到二进制 data 数据段中
上面是和正常泛型参数结合的例子,, 第一个 是生命周期,第二个是泛型 , 要求实现 trait. 注意这里面顺序不能颠倒,如果 放到前面会报错
函数签名里的标注
这个例子就会报错,虽然我们指定了生命周期,但没什么用。 在语句块结束后就被释放了,println resut 时继续使用 string2 的引用就是非法的。把 println 放在语句块内就可以了
多个生命周期参数
如果函数有多个生命周期参数,, , 返回引用是 , 此时编译会报错
原理很简单,编译器无法确定这两个 lifetimes 的有效长度,需要指定约束
最终函数如上所示,其中 表示 一定包括 生命周期长度
结构体内的标注
在结构体定义时,如果存在引用,也要写上 注释,泛型语法这里不再赘述了。 是一个字符串引用,在实例 创建前就存在了,并且和 同时离开作用域被释放
如果去掉泛型的 lifetime 注释,就会报错
结构体方法的标注
结构体方法的标注语法要在 关键字后写上 , 并在结构体名后使用。这个例子中并没有在 中标注,这里引出另一条规则如果方法有多个输入生命周期参数并且其中一个参数是 &self 或 &mut self,说明是个对象的方法(method), 那么所有输出生命周期参数被赋予 self 的生命周期
假如把 返回值换成 就会报错
这时需要显示的指定来协助编译器来完成检查,指定 lifetime. 另外涉及子类型,协变,逆变时生命周期会更复杂一些,感兴趣的可以参考nomicon[2]官方文档
小结
杂七杂八写了堆,建议家还是上手多练,多琢磨。以前刚学 rust 时,有人说编译不过的话,生命周期就加 , 数据就多用
其实呢,还是要理解本质,和 Go GC 运行期遍历不同,检查器要在编译期确定资源何时何处释放,就需要收集额外的信息。比如说,结构对象有个引用字段。如果无法确认它的生命周期,那么结构对象释放时,是否要释放该字段?还是说该字段可以提前自动释放,是否导致悬垂引用?显然,这违反了安全规则
再次强调,Rust 为了所谓的零运行时成本,把很多 GC 语言的工作放到了编译期
写文章不容易,如果对家有所帮助和启发,请家帮忙点击,, 三连
关于 家有什么看法,欢迎留言一起讨论,牛多留言 ^_^
参考资料[1]
the rust book:https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html,
[2]
subtyping-and-variance:https://doc.rust-lang.org/nomicon/subtyping.html#subtyping-and-variance,
免责声明:文中图片均来源于网络,如有版权问题请联系我们进行删除!
标签: