当前播放: 41 | 借用检查: 深入理解生命周期参数Early bound
00:00 / 00:00
高清
  • 高清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看
课程目录
第一章:Rust语言基础 (32讲)
01 | 课程介绍
免费
02 | 内容综述
免费
学习方法推荐与课程组织逻辑
免费
03 | Rust语言学习观
免费
04 | Rust语言概览
05 | 语法面面观:词法结构
06 | 语法面面观:面向表达式(上)
07 | 语法面面观:面向表达式(中)
08 | 语法面面观:面向表达式(下)
09 | 语法面面观:数据类型 (上)
10 | 语法面面观:数据类型 (下)
11 | 语法面面观:函数与闭包(上)
12 | 语法面面观:函数与闭包(中)
13 | 语法面面观:函数与闭包(下)
14 | 语法面面观:模式匹配
15 | 语法面面观:智能指针(上)
16 | 语法面面观:智能指针(下)
17 | 语法面面观:字符与字符串(上)
18 | 语法面面观:字符与字符串(下)
19 | 语法面面观:集合容器(上)
20 | 语法面面观:集合容器(下)
21 | 语法面面观:迭代器(上)
22 | 语法面面观:迭代器(下)
23 | Rust语法面面观:模块
24 | Rust 语法面面观:Cargo包管理器(上)
25 | Rust 语法面面观:Cargo包管理器(下)
26 | 语法面面观:实际项目的组织结构(上)
27 | 语法面面观:实际项目的组织结构(下)
28 | 语法面面观:定义自己的Crate(上)
29 | 语法面面观:定义自己的Crate(中)
30 | 语法面面观:定义自己的Crate(下)
31 | 作业&第二章预告
第二章:Rust语言核心概念 (56讲)
32 | 本章内容介绍:Rust语言架构
33 | 所有权:内存管理基础知识
34 | 所有权:安全管理之内存安全
35 | 所有权:Copy语义和Copy trait
36 | 所有权:深入理解Copy行为
37 | 所有权:深入理解Move语义
38 | 所有权:Move与析构
39 | 借用检查: 完全理解Scope和NLL
40 | 借用检查: 深入理解生命周期和生命周期参数
41 | 借用检查: 深入理解生命周期参数Early bound
42 | 借用检查:深入理解生命周期参数Tvs&T
43 | 借用检查: 深入理解生命周期参数: trait对象的生命周期参数
44 | 借用检查: 深入理解生命周期参数:高阶生命周期(上)
45 | 借用检查: 深入理解生命周期参数:高阶生命周期(中)
46 | 借用检查: 深入理解生命周期参数:高阶生命周期(下)
47 | 线程与并发:理解线程与并发
48 | 线程与并发:线程间安全共享数据
49 | 线程与并发:构建「无悔」并发系统(一)
50 | 线程与并发:构建「无悔」并发系统(二)
51 | 线程与并发:构建「无悔」并发系统(三)
52 | 线程与并发:构建「无悔」并发系统(四)
53 | 线程与并发:无锁并发(上)
54 | 线程与并发:无锁并发(中)
55 | 线程与并发:无锁并发(下)
56 | trait与泛型:trait静态分发
57 | trait与泛型:认识trait对象
58 | trait与泛型:泛型和trait实现模板方法
59 | trait与泛型:trait对象本质
60 | trait与泛型:对象安全本质
61 | trait与泛型:利用Enum代替trait对象
62 | trait与泛型:trait覆盖实现的一个解决方案
63 | trait与泛型:trait对象与Sized
64 | trait与泛型:trait对象与Box Self
65 | 编程范式:Rust语言编程范式讨论(上)
66 | 编程范式:Rust语言编程范式讨论(下)
67 | Rust错误处理概要
68 | Rust错误处理:Option
69 | Rust错误处理:Result(上)
70 | Rust错误处理:Result(下)
71 | Rust错误处理:try
72 | Rust错误处理:Panic
73 | Rust元编程之反射
74 | Rust元编程之反射的两种应用思路
75 | Rust元编程之编译过程与宏展开概述
76 | Rust元编程之声明宏上
77 | Rust元编程之声明宏下
78 | Rust元编程之过程宏三件套介绍
79 | Rust元编程之过程宏之Bang宏实现原理
80 | Rust元编程之过程宏-使用配置文件动态生成代码
81 | Rust元编程之过程宏Derive宏案例
82 | Rust元编程之过程宏属性宏
83 | 客观理解Unsafe Rust
84 | Unsafe Rust之安全抽象
85 | Unsafe Rust安全抽象之Drop检查
86 | Unsafe Rust安全抽象之型变
87 | UnsafeRust之其他
第三章:Rust异步编程基础 (11讲)
88 | Rust异步编程之IO模型
89 | Rust异步编程之epoll和io_uring
90 | Rust异步编程之事件驱动编程模型
91 | Rust异步编程之epoll代码实践
92 | Rust异步编程之Reactor代码实践
93 | Rust异步编程之MiniMio代码实践
94 | Rust异步编程之Mio代码实践(上)
95 | Rust异步编程之Mio代码实践(下)
97 | Rust异步编程之Future和Futures-rs介绍
96 | Rust异步编程之异步编程模型概要
98 | Rust异步编程之编写异步echo服务(上)
41 | 借用检查: 深入理解生命周期参数Early bound

41 | 借用检查: 深入理解生命周期参数Early bound

张汉东
《Rust编程之道》作者
每周四 17:00更新3992
新人首单 ¥59.9 原价 ¥129
5
本节摘要
登录 后留言

精选留言(7)

  • 刘康
    上一节中提到,输入的引用的生命周期要大于等于输出的,这一节中多个地方说错。
    2021-02-25
    1
    1
  • 易水
    张老师我是这样理解的:

    ```rust
        fn read_bytes(&mut self) -> &'a [u8] {
            self.pos += 3; // 后面不需要可变引用, 可变引用只持续到这里.
            &self.buf[self.pos - 3..self.pos]
        }
    }

    fn main() {
        let v = vec![1, 2, 3, 4, 5, 6];
        let mut buf = Buffer::new(&v);
        let b1 = buf.read_bytes(); // buf的可变引用在函数内部就结束了
        let b2 = buf.read_bytes(); // buf的可变引用在函数内部就结束了
        print(b1, b2);
    }
    ```

    输出生命周期必须和输入生命周期相关联, 本例中 read_bytes 真正的和输出生命周期相关联的输
    入生命周期是 Buffer::buf 的生命周期, 让 read_bytes 输出的生命周期和 Buffer::buf 的生
    命周期保持一致, 就保证了输出生命周期小于等于输入生命周期.

    上面的为什么可以执行两次 `buf.read_bytes`, 执行两次 `buf.read_bytes` 之后还可以打印 b1, b2

    因为 `fn read_bytes(&mut self) -> &'a [u8]` 返回的生命周期和 `Buffer::buf` 也就是 `&v`
    的生命周期一致, 都是 `'a`. 两次调用 `buf.read_bytes` 返回的 b1 和 b2 的生命周期都是 `&v`
    的生命周期. 而实例 buf 的可变引用在 `read_bytes` 函数中的 `self.pos += 3;` 那一行就结束了.

    实例 buf 的可变引用在 `read_bytes` 函数内部就结束了. 所以可以重复调用 `read_bytes`, 并且
    调用之后还可以访问其返回值 `b1`, `b2`.

    ----------------------------------------

    如果改成下面的

    ```rust
        fn read_bytes(&mut self) -> &[u8] {
            self.pos += 3;
            &self.buf[self.pos - 3..self.pos]
        }
    }

    fn main() {
        let v = vec![1, 2, 3, 4, 5, 6];
        let mut buf = Buffer::new(&v);
        let b1 = buf.read_bytes();
        let b2 = buf.read_bytes();
        println!("{:#?}",b2); // 这个是可以的

        // 下面的会编译报错, 因为使用 b1 会使 b1 那里的对应的buf的可变借用的生命周期延长,
        // 延长之后的可变借用的生命周期会覆盖到 b2 的生命周期那一行. 会造成多次可变借用的情况.
        // println!("{:#?} {:#?}", b1, b2);
    }
    ```

    因为改成 `fn read_bytes(&mut self) -> &[u8]` 之后, 实例 buf 的可变引用的生命周期和返回
    值的生命周期一致, 由于 NLL 虽然也可以连续调用 `read_bytes` 多次, 但是无法使用第一次调用返
    回的值, 只能使用最后一次返回的值, 因为如果使用第一次返回的值, 会让第一次 buf 的可变借用生命
    周期延长到使用的那个地方, 就会造次多次可变借用的情况.

    2021-01-16
    1
    2
  • 未成熟的稚气_
    反复看了两三遍,终于看懂了!🙏
    2020-12-29
    2
    1
  • 学不完不改名
    张老师牛逼, 居然还发现了早绑定晚绑定的用法
    2020-12-19
    1
  • 陈顺吉
    没懂为什么 let pf = f::<'static> as fn(); 是 late bound,let pg = g::<'static> as fn(); 就是 early bound
    2021-01-17
    1
  • 易水
    输出生命周期必须和输入生命周期相关联, 本例中 read_bytes 真正的和输出生命周期相关联的输
    入生命周期是 Buffer::buf 的生命周期, 让 read_bytes 输出的生命周期和 Buffer::buf 的生
    命周期保持一致, 就保证了输出生命周期小于等于输入生命周期. 从而可以编译执行. 这比分析early
    或 late bound要简单些.
    2021-01-16
    2
  • 易水
    示例二:用两个生命周期参数是 early bound, 只用一个生命周期参数是 late bound

    impl<'a> Buffer<'a> {
        ...
        fn read_bytes(&mut self) -> &'a [u8] {
        ...
    }

    // 下面是测试late bound的代码
    //error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
    //let a = Buffer::read_bytes::<'static>;

    改成只有一个生命周期参数会变成late bound,也可以正常编译执行.

    是不是可以这么认为, 不管是early还是late bound都能满足要求,最主要的还是需要保证 read_bytes 的输出生命周期和 Buffer::buf 这个成员的生命周期一致就可以解决这个问题呢?
    2021-01-16
收起评论
看过的人还看
数据结构与算法之美

王争  前Google工程师

81讲 | 110803 人已学习

新人首单 ¥69.9 原价 ¥199
左耳听风

陈皓  网名“左耳朵耗子”,资深技术专家,骨灰级程序员

118讲 | 56933 人已学习

新人首单 ¥99 原价 ¥299
MySQL实战45讲

林晓斌  网名丁奇,前阿里资深技术专家

49讲 | 76618 人已学习

新人首单 ¥69.9 原价 ¥199
设计模式之美

王争  前Google工程师,《数据结构与算法之美》专栏作者

113讲 | 39089 人已学习

新人首单 ¥99 原价 ¥299