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. Using-jqGrid-s-search-toolbar-with-multiple-filter

    http://www.codeproject.com/Articles/58357/Using-jqGrid-s-search-toolbar-with-multiple-filter

  2. 共享内存shared pool (4):Library cache 转储文件

    上一篇blog只是从概念上理解Library cache,本篇则是将Library cache从内存中dump出来,看看其结构. 基本命令 ALTER SESSION SET EVENTS 'imme ...

  3. 【C#】使用C#将类序列化为XML

    直接上代码: public static class XmlSerializer { public static void SaveToXml(string filePath, object sour ...

  4. SQL基础篇——如何搭建一个数据库

    特别提醒:所有的新建数据库,表,行,列都可以通过对象资源管理器操作,下面所讲的为查询操作方法 一.新建数据库 使用CREATE DATABASE语句建立数据库: 新建查询-- CREATE DATAB ...

  5. L2-015. 互评成绩

    学生互评作业的简单规则是这样定的:每个人的作业会被k个同学评审,得到k个成绩.系统需要去掉一个最高分和一个最低分,将剩下的分数取平均,就得到这个学生的最后成绩.本题就要求你编写这个互评系统的算分模块. ...

  6. .NET开源工作流RoadFlow-快速入门

    在环境搭建好之后,我们就来学习一下怎样快速创建一个流程,并执行和流转该流程(我们这里讲的只是入门,不涉及到具体流程参数设置). 创建一个流程步骤为:在数据库在创建表-->设计表单-->设置 ...

  7. Reverse String

    Write a function that takes a string as input and returns the string reversed. Example:Given s = &qu ...

  8. DHCP Server软件使用教程

    DHCP Server软件使用教程 前提网络环境配置 电脑连接上wifi 网络和共享中心中更改适配器,共享无线网卡给以太网网卡 手动设置以太网网卡ipv4地址为192.168.1.1,子网掩码为255 ...

  9. Introduction to Haskell

    "I know why you're here. ...why you hardly sleep, why night after night, you sit by your comput ...

  10. P3384: [Usaco2004 Nov]Apple Catching 接苹果

    一道DP题, f[i,j,k] 表示 第 k 时刻 由 1 位置 变换 j 次 到达 当前 i 棵树 注意也要维护 变换 0 次的情况. var i,j,k,t,w,now:longint; tree ...