按关键词阅读:
正好刚写了篇文章,供参考:Rust所有权语义模型 - 专栏
■网友
【咋通俗的理解Rust中的生命周期】 简短回答:生命周期代表资源的可用时期。显式生命周期标记是泛型参数的一种,但是有协变的概念。长生命周期作为短生命周期的子类型,此处与直觉相反。
——详细回答分割线——
声明一个变量,其生命周期开始,变量离开作用域,其生命周期结束。
以上是生命周期的基本概念,和其他语言相比并没有什么不同。
题主想问的是生命周期标记吧?
生命周期标记一般标记于复合类型(结构体)、函数、枚举类型,仅当与引用(借用)相关联时。多数情况下生命周期标记可以由编译器为我们推导并标注。一些情况需要程序员显式写出生命周期标记。在函数中,需要显式写出生命周期时,一般是在需要返回参数相关的引用时。(返回堆分配内存时,直接返回Vec\u0026lt;T\u0026gt;或Box\u0026lt;T\u0026gt;)
struct Name\u0026lt;\u0026#39;a, \u0026#39;b\u0026gt; { first: \u0026amp;\u0026#39;a String, last: \u0026amp;\u0026#39;b String,}
在上述Struct Name的声明中,first和last的生命周期都不得短于Struct的生命周期。注意此处是不得短于,因为若内部值的生命周期更短,则出现无效引用。
此时生命周期标记代表什么?作用又是什么?生命周期标记是一种泛型参数,这是The Book提到的。但光认识到这一点还不够。因为即使指定了生命周期的约束关系,也会发现约束“似乎不起作用”:
fn do_sth\u0026lt;\u0026#39;a, \u0026#39;b, \u0026#39;c\u0026gt;(arg1: \u0026amp;\u0026#39;a i32, arg2: \u0026amp;\u0026#39;b i32) -\u0026gt; \u0026amp;\u0026#39;c i32 where \u0026#39;a: \u0026#39;b, \u0026#39;b: \u0026#39;c { arg2}
do_sth函数中,约束的生命周期关系为:arg1 \u0026gt;=arg2,arg2 \u0026gt;= arg3,越大则生命周期越长。但你还是可以这么调用:
fn main() { let mario = 1; let ref1 = \u0026amp;mario; { let luigi = 2; let ref2 = \u0026amp;luigi; { let peach = do_sth(\u0026amp;ref2, \u0026amp;ref1); } }}
初学者会认为:明明指定了arg1的参数生命周期应该更长,却不报错??让初学者更加懵逼的是,把函数签名的生命周期标记都改成一样的,还是能够通过编译。
这就涉及到另一个概念——协变(Covariant)了。如果对面向对象熟悉的话,有一个规则叫里氏代换。协变和里氏代换很像,都是“接受父类型的位置,子类型也可以占位”。在Rust中,范围更大的类型可以作为范围更小的类型的父类型,例如i16是i8的父类型,反过来i8是i16的子类型。
但对于生命周期而言,反而是生命周期长的类型作为生命周期短的类型的子类型。前面提到Struct中,内部域生命周期和结构本身生命周期的关系是不短于。如果生命周期短的类型作为生命周期长的类型的子类型,则在函数体中,无法保证引用参数的有效性。因为当父类型生命周期可以覆盖整个函数体过程,子类型无法作出这样的保证。
■网友
看RustPrimer,也在学习Rust,但对这个生命周期的概念,我想我是讲不太清楚的。
■网友
生命周期 | RustPrimer这篇文章说的比较清楚
来源:(未知)
【】网址:/a/2020/0401/gd358788.html
标题:咋通俗的理解Rust中的生命周期