Rust 语言从入门到实战
唐刚
Rust 语言中文社区联合创始人
5266 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 36 讲
Rust 语言从入门到实战
15
15
1.0x
00:00/00:00
登录|注册

03|所有权(下):Rust中借用与引用的规则是怎样的?

你好,我是 Mike。今天我们继续探讨 Rust 中所有权这一关键设计。
上节课我们了解了计算机内存结构知识,理解了 Rust 在内存资源管理上特立独行的设计——所有权,也知道了 Rust 准备采用所有权来重构整个软件体系。那么这节课我们继续学习所有权的相关内容——借用与引用,学完这节课我们就会对 Rust 语言的所有权方案有一个相对完整的认知了。
这节课我会用一些精心设计的示例,让你体会 Rust 引用的独特之处。

借用与引用

我们来复习一下上一节课最后一个例子。我们想在函数 foo 执行后继续使用字符串 s1,我们通过把字符串的所有权转移出来,来达到我们的目的。
fn foo(s: String) -> String {
println!("{s}");
s
}
fn main() {
let s1 = String::from("I am a superman.");
let s1 = foo(s1);
println!("{s1}");
}
这样可以是可以,不过很麻烦。一是会给程序员造成一些心智负担,还得想着把值传回来再继续使用。如果代码中到处都是所有权传来传去,会让代码显得相当冗余,毕竟很多时候函数返回值是要用作其他类型的返回的。为了解决这个问题,Rust 引入了借用的概念。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Rust语言中的所有权和引用是其设计的关键特点之一。本文深入探讨了借用与引用规则,介绍了不可变引用和可变引用的概念,并通过示例展示了如何使用引用。文章指出了在Rust中,所有权型变量和引用型变量都由编译器维护着值和类型的信息。接着,通过多个示例展示了引用的使用时机和作用域规则,以及可变引用与不可变引用的交叠限制。文章强调了理解引用的最后一次调用时机的重要性,并提出了分析每个示例的方法。此外,文章还介绍了多级引用的语言细节和用引用改进函数定义的方法。通过这些内容,读者可以深入了解Rust语言中的所有权和引用概念,以及相关的规则和限制。总体而言,本文为想要深入了解Rust语言的读者提供了非常有价值的内容。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Rust 语言从入门到实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(31)

  • 最新
  • 精选
  • Andylinge
    1. 不可变引用的作用域跨越了所有权变量的写入过程,意味着同一个作用域同时存在可变引用和不可变引用,编译器为了防止读取错误,不能通过编译。可以把a = 20放到引用之前,即可编译通过。 2. 可变引用如果可以Copy,就违反了可变引用不能同时存在的规则,因此只能Move. 跟唐老师学习我觉得我理解能力变强了,感谢唐老师的课程,扫清了很多基础的迷雾。

    作者回复: 很棒,对的,基础扫清了才能启航远洋。

    2023-10-26归属地:安徽
    2
    18
  • Michael
    想请问下下面这段代码,为什么变量b之前的mut是必须的,变量c之前不需要: fn main() { let mut a1 = 10u32; let mut b = &mut a1; *b = 20; let c = &mut b; **c = 30; // 多级解引用操作 println!("{c}"); }

    作者回复: 因为后面c要对b进行可变借用。这样,语法上就要求b在前面加mut修饰。你如果后面再有d对c进行可变借用,那么你试试,c也需要加mut修饰的。

    2023-10-26归属地:中国香港
    2
    6
  • 一个人旅行
    问题1. 所有权型变量被借用时,不能对所有权型变量进行修改。 问题2. 同一时刻,所有权型变量只能有一个可变引用或多个不可变引用。如果复制,则会有多个不可变引用,违反了借用规则。

    作者回复: 不错。

    2023-10-26归属地:北京
    2
    5
  • Lin
    rust完全模拟了现实世界中借的概念,a有一本书,b要用的时候向a借,b不能超出a的移动范围(作用域范围),因为怕借了不还跑路了。

    作者回复: 有趣🤔️

    2023-10-27归属地:北京
    2
    4
  • RobinH
    所有权 感觉像是一种 栈范围 在控制

    作者回复: 你的直觉非常准👍👍, 最后一篇总结揭开谜底

    2024-01-22归属地:湖北
    2
  • -Hedon🍭
    1. 不可变引用的语义更像是“借一下这个值使用一下”,如果在不可变引用作用域结束之前,对所有权变量进行写入,那么这个借的“值”,就没有意义了,因为不确定是否跟想借的时候是一致的。 2. 如文中所说,可变引用的作用域不能交叉,如果采用 copy,则两份可变引用其实是互不影响的,即可以交叉,就产生矛盾了。

    作者回复: 很棒。

    2023-10-25归属地:湖北
    2
  • weineel
    一句话总结:资源在借用期间不能被修改(包括定义可变借用)

    作者回复: 你是说原资源所有权变量在借用期间不能用来修改资源吧?

    2023-12-19归属地:江苏
    2
    1
  • javpower
    借用规则类似于读写锁,即同一时刻只能拥有一个写锁,或者多个读锁,不允许写锁和读锁同时出现。这是为了避免数据竞争,保障数据一致性。

    作者回复: 对的

    2023-11-11归属地:江西
    1
  • 小云同学
    1. 如果换个例子就好解释了 fn main() { let mut s = "hello".to_string(); let p = &s; // 不可变借用 s.push_str(" world"); // 可变借用 println!("{}", p); // 不可变借用 } 由于不可变借用和可变借用的范围出现了重叠,因此编译出错。而 a = 20 和此处类似,都是修改了实际数据。 2. 因为多个可变引用的作用范围不能存在交集,所以 Copy 的话没有意义,因此只能 Move

    作者回复: 很棒!

    2023-11-01归属地:北京
    1
  • 励研冰
    从语意上保证了安全性,不可变引用语意:从此刻开始到我的运用域结束,原始值请保持我开始的状态,不然就破坏了我的不可变引用的语;可变引用同样的道理;。类似于mysql中的可重复读事物,不过mysql的实现方式是通过mvcc ,为了提高并发度;而rust是限制修改,更像是排斥锁,不允许交叉;不过这样的话不知道后面的 无谓并发 在对同一个数据的修改上会不会有什么问题

    作者回复: 思考得很棒,后面会看到关于所有权在并发中的处理相关内容。

    2023-10-26归属地:上海
    1
收起评论
显示
设置
留言
31
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部