Rust的lifetime算是它最重要的特性之一,也不大好理解,特别是官方文档的介绍有些太过简略,容易让人误解。

这篇文章:

Rust Lifetimes

应该可以解答很多人疑惑,特别是有关lifetime的一些基础性的知识。

同时,参照其它的文章,在于总结一下关于Rust语言里的lifetime语法。

1. “lifetime”是指谁的lifetime?

lifetime是指reference的lifetime。它并不对应资源的生命周期,那是由move和borrow来控制的。同样,函数也是没有生命周期的,所以函数

fn foo<'a>(c: &'a i32) -> &'a i32

里的'a跟函数本身在何处被使用没有关系,它是被参数c的生命周期赋值的。

同时,&'a代表了一个生命周期为a的引用, 它们是一起的,比如,不会有&mut 'a,而是得写成&'a mut.

2. lifetime用来做什么?

来让编译器可以确定访问一个reference引用的对象是否安全。可以确保不会发生“use after free"错误,因此能让数据被安全地共享。

3. lifetime的值?

是什么?

首先,得明确一个”reference"的生命周期是什么?

 fn foo() {
     let a = &1;
     let b = a;
     ...
 }

一个reference的生命周期就是指在哪个代码区间可以用这个reference。比如,在上边的例子中,a可以在第2行至第4行被使用,b可以在第3行至第4行被使用。这个范围在代码编译时就确定了,不会延伸到任何其它区域,因为reference并不存在move和borrow这种语法,reference始终都是按值copy的。

还有一个隐晦但我不能确定的地方,从各种例子上看,假如我们在第4行去评估a和b的lifetime,那么它们是相等的。所以,看起来当lifetime被真正求值的时候,它的值的起点是被求值的那一行,终点是它不能再被使用的地方(在上例中是最后一个花括号)。

如何赋值?

lifetime的抽象程序使得它不合适程序员显式地指明其值。每个reference相关的lifetime的值都是由编译器确定的。

程序员能做的是将一个reference传给函数,同时这个reference的lifetime也会被传给这个函数作为参数。例如:

fn main() {
    let a = &1;
    let b = a;
    let c = foo(a, b);
    println!("{}", c);
}

fn foo<'a>(first: &'a i32, second: &'a i32) -> &'a i32 {
    return second;
}

在调用foo时,a和b的lifetime被传给foo,使得foo的签名中的'a有了确定的值,因此返回值的lifetime也被确定。此时,如果返回值被赋值到的引用的lifetime比'a大,那么编译器就会报错。

注意,这里c的lifetime可以比'a要小,这里的小是指,它的lifetime被'a包括。

比如,可以这样:

fn main() {
    let a = &1;
    let b = a;
    {
        let c = foo(a, b);
    }
    println!("{}", a);
}

4 编译器检查lifetime的规则是什么?

这个可以看这篇文章:生命周期( Lifetime )

要推导Lifetime是否合法,先明确两点:

  • 输出值(也称为返回值)依赖哪些输入值
  • 输入值的Lifetime大于或等于输出值的Lifetime (准确来说:子集,而不是大于或等于)

Lifetime推导公式: 当输出值R依赖输入值X Y Z ...,当且仅当输出值的Lifetime为所有输入值的Lifetime交集的子集时,生命周期合法。

    Lifetime(R) ⊆ ( Lifetime(X) ∩ Lifetime(Y) ∩ Lifetime(Z) ∩ Lifetime(...) )

 

Rust: lifetime的更多相关文章

  1. Rust <8>:lifetime 高级语法与 trait 关联绑定

    一.生命周期关联:如下声明表示,'s >= 'c struct Parser<'c, 's: 'c> { context: &'c Context<'s>, } ...

  2. Rust: move和borrow

    感觉Rust官方的学习文档里关于ownship,borrow和lifetime介绍的太简略了,无法真正理解这些语法设计的原因以及如何使用(特别是lifetime).所以找了一些相关的blog来看,总结 ...

  3. Rust入门篇 (1)

    Rust入门篇 声明: 本文是在参考 The Rust Programming Language 和 Rust官方教程 中文版 写的. 个人学习用 再PS. 目录这东东果然是必须的... 找个时间生成 ...

  4. A First Look at Rust Language

    文 Akisann@CNblogs / zhaihj@Github 本篇文章同时发布在Github上:http://zhaihj.github.io/a-first-look-at-rust.html ...

  5. 【转】对 Rust 语言的分析

    对 Rust 语言的分析 Rust 是一门最近比较热的语言,有很多人问过我对 Rust 的看法.由于我本人是一个语言专家,实现过几乎所有的语言特性,所以我不认为任何一种语言是新的.任何“新语言”对我来 ...

  6. rust 参考的资料 转

    http://blog.csdn.net/loveisasea/article/details/46292715 rust官方学习文档: 1.http://doc.rust-lang.org/book ...

  7. 2.4 Rust Ownership

    What Is Ownership ownership这个单词有些不好翻译,刚开始就直接叫它“ownership”即可.这里简单说一下,我对它的理解, 从“数据结构与算法”的角度来看,ownershi ...

  8. Rust 内存管理

    Rust 内存管理 Rust 与其他编程语言相比,最大的亮点就是引入了一套在编译期间,通过静态分析的方式,确定所有对象的作用域与生命周期,从而可以精确的在某个对象不再被使用时,将其销毁,并且不引入任何 ...

  9. Rust所有权语义模型

    编程语言的内存管理,大概可以分为自动和手动两种. 自动管理就是用 GC(垃圾回收)来自动管理内存,像 Java.Ruby.Golang.Elixir 等语言都依赖于 GC.而 C/C++ 却是依赖于手 ...

随机推荐

  1. delphi 基础之三 文件流操作

    文件流操作 Delphi操作流文件:什么是流?流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具.在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的, ...

  2. Python之Flask Web开发

    下载python包管理工具Pip: 访问网址:https://pip.pypa.io/en/stable/installing/    下载文件get-pip.py到本地计算机 定位到get-pip. ...

  3. 计算两条直线的交点(C#)

    PS:从其他地方看到的源码是有问题的.下面是修正后的 /// <summary> /// 计算两条直线的交点 /// </summary> /// <param name ...

  4. OXPattern

    10000的随机数组由ox组成,查找数组中oox...x(任意x)oox....x(任意x)o的个数 enum { DATA_SIZE = , }; enum enum_status { STATUS ...

  5. 在EF的code frist下写稳健的权限管理系统:界面设计(四)

    基本都是采用pure设计(中文官网:http://purecss.org,英文官网:http://purecss.io).pure只是一个简单强大的cssUI库,支持响应式设计,适合自己设计或者给美工 ...

  6. 7.css盒模型

    所谓的盒模型,其实就是把元素当成盒子,元素里的文本就是盒子里的东西. 而根据元素的特效,其盒模型的特效也不同,下面是一些总结: 1.块级元素(区块) 所谓块级元素,就是能够设置元素尺寸.有隔离其他元素 ...

  7. 3.css中的颜色

    css中颜色的设置形式主要有三种方式:颜色名称.十六进制代码和十进制代码. 在古老的 HTML4 时,颜色名称只有 16 种. 颜色名称 十六进制代码 十进制代码 含义  black  #000000 ...

  8. MongoDB 学习笔记(二)—— MongoDB Shell

    MongoDB自带一个JavaScript shell 可以从命令行中与MongoDB交互,功能非常强大.如在上一节最后一张图所看到,可以执行JavaScript程序. 运行Shell 前提是启动Mo ...

  9. equals函数

    equals函数在Object类当中,而Object类是所有类的父类,所以所有的类里面都有equals函数. “==”操作符之前用于比较两个基本数据类型的值是否相等,而对于引用数据类型,“==”操作符 ...

  10. C 基于UDP实现一个简易的聊天室

    引言 本文是围绕Linux udp api 构建一个简易的多人聊天室.重点看思路,帮助我们加深 对udp开发中一些api了解.相对而言udp socket开发相比tcp socket开发注意的细节要少 ...