陈天 · Rust 编程第一课
陈天
Tubi TV 研发副总裁
新⼈⾸单¥59.9
2556 人已学习
课程目录
已更新 9 讲 / 共 41 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词|让Rust成为你的下一门主力语言
免费
前置篇 (3讲)
01|内存:值放堆上还是放栈上,这是一个问题
02|串讲:编程开发中,那些你需要掌握的基本概念
加餐| Rust真的值得我们花时间学习么?
基础篇 (5讲)
03|初窥门径:从你的第一个Rust程序开始!
04|get hands dirty:来写个实用的CLI小工具
05|get hands dirty:做一个图片服务器有多难?
06|get hands dirty:SQL查询工具怎么一鱼多吃?
07|所有权:值的生杀大权到底在谁手上?
陈天 · Rust 编程第一课
15
15
1.0x
00:00/00:00
登录|注册

07|所有权:值的生杀大权到底在谁手上?

你好,我是陈天。
完成了上周的“get hands dirty”挑战,相信你对 Rust 的魅力已经有了感性的认知,是不是开始信心爆棚地尝试写小项目了。
但当你写的代码变多,编译器似乎开始和自己作对了,一些感觉没有问题的代码,编译器却总是莫名其妙报错。
那么从今天起我们重归理性,一起来研究 Rust 学习过程中最难啃的硬骨头:所有权和生命周期。为什么要从这个知识点开始呢?因为,所有权和生命周期是 Rust 和其它编程语言的主要区别,也是 Rust 其它知识点的基础
很多 Rust 初学者在这个地方没弄明白,一知半解地继续学习,结果越学越吃力,最后在实际上手写代码的时候就容易栽跟头,编译总是报错,丧失了对 Rust 的信心。
其实所有权和生命周期之所以这么难学明白,除了其与众不同的解决内存安全问题的角度外,另一个很大的原因是,目前的资料对初学者都不友好,上来就讲 Copy / Move 语义怎么用,而没有讲明白为什么要这样用
所以这一讲我们换个思路,从一个变量使用堆栈的行为开始,探究 Rust 设计所有权和生命周期的用意,帮你从根上解决这些编译问题。

变量在函数调用时发生了什么

首先,我们来看一看,在我们熟悉的大多数编程语言中,变量在函数调用时究竟会发生什么、存在什么问题。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/1000字
划线
笔记
复制
该试读文章来自付费专栏《陈天 · Rust 编程第一课》,如需阅读全部文章,
请订阅文章所属专栏新⼈⾸单¥59.9
立即订阅
登录 后留言

精选留言(8)

  • pedro
    1,在 Rust 下,分配在堆上的数据结构可以引用栈上的数据么?为什么?

    可以,以 Vec 为例,它可以存储栈上的引用,但必须注意一点那就是该引用的生命周期不能超过栈上数据的生命周期。

    2,main() 函数传递给 find_pos() 函数的另一个参数 v,也会被移动吧?为什么图上并没有将其标灰?

    很简单,i 是原生类型,默认实现了 Copy 语义,在传参时,默认不再是移动而是 copy。

    提一下,rust 的参数传递是反直觉的,默认为 move 和不可变,而其它主流语言默认都是 copy 和可变的,想要达到一样效果,必须实现 Copy 以及加上 mut。

    要充分记住这一点,这是 rust 安全的生命线。
    2021-09-06
    2
  • Henry
    1: 实验了下可以,并找不出 Rust 限制不让这么做的理由;
    2: u32 时下了 Copy Trait,所以 copy 了一个新的值赋给了函数函数,所以 v 在后续依然可以引用
    2021-09-06
  • Kevin
    文中的v是基数类型数组类型,已经实现了Copy,所以不需要手动Copy
    2021-09-06
  • gnu
    因为 v 是 u32 类型实现了 Copy trait,且分配在栈上,调用 find_pos 时 Copy 了一份 v',所以图里不用值灰。
    2021-09-06
  • 阿海
    堆上的数据可以引用栈上的数据,但两者要有相同的生命周期;v是基本数据类型,实现了copy,find_pos里的v是另一个存储在栈上的数据
    2021-09-06
  • pedro
    另外对按位复制补充一点:

    按位复制,等同于 C 语言里的 memcpy。

    C 语言中的 memcpy 会从源所指的内存地址的起始位置开始拷贝 n 个字节,直到目标所指的内存地址的结束位置。但如果要拷贝的数据中包含指针,该函数并*不会*连同指针指向的数据一起拷贝。

    因此如果是不包含指针的原生类型,那么按位复制(浅拷贝)等同于 clone,可如果是 Vec 这种在堆上开辟,在栈上存储胖指针的数据就不一样了,因为按位复制会拷贝胖指针本身,而其指向的堆中数据则不会拷贝,因此堆上的数据仍然只有一份。

    最后,最好不用去实现 Copy。
    2021-09-06
  • blackonion
    可以理解为是否实现copy trait主要看rust编译器能否在编译时就能确定所需大小吗?
    2021-09-06
  • springXu
    问题1.我认为不能。它违背了单一所有权的原则。
    问题2.let v的类型是基本数据类型,它是实现了Copy trait的。 所以学完本节内容第二题是能回答的。
    2021-09-06
收起评论
8
返回
顶部