【未经书面同意,严禁转载】 -- 2020-10-14 --
所有权是Rust的重中之重(这口气咋像高中数学老师 WTF......)。
所有权是指的对内存实际存储的数据的访问权(包括读取和修改),在大多数语言中,一个数据赋值给一个变量,这个变量就拥有了数据的访问权。然后可以定义很多引用指向这个变量和这段数据,所有的引用都可以修改它。但在Rust中刷新了这种观念:读数据可以共享,但写数据必须是独占的!这样就能保证数据安全性,以及并发过程中的数据竞争。Rust用所有权来实现这一切。
所有权和另外两个概念借用和生命周期是相关的,可以说是一体的。借用其实就是前面讲的引用干的事情。大多数Rust书籍——包括官网的《The Book》——都是按章节一 一介绍,总感觉不那么立体,理解起来也慢。
引用(借用):borrowing
所有权:ownership
生命周期:lifetimes
搞定三者应该是一揽子工程。
经闭关苦思冥想,我总结了一个形象的比喻,和读者分享。
每个人都有一张身份证,来记录个人的唯一信息身份证号,以及姓名:张三、性别:男 等个人信息,你可以以这个身份拥有房产、汽车、存款等财物(相当于内存中的实际数据),并可以修改房产的布局、启动汽车、存取款。这些财物属于这个身份的,这个身份拥有这些财物,这个身份对财物拥有所有权。这个时候,任何其他人无权进你的房间、汽车、私自查你的账户。
如果李四向张三打了招呼:我想去你房子里看看,张三允许了李四去参观房子、查看账户,但此时未经张三的书面允许还不能去搬动或迁移财物。借用者只能使用,不能改变,这是只读引用,也叫共享引用,因为可以有多人同时使用,这时候王五、赵六都可以同时去查看张三的财物信息。
然而如果有胡七取得了张三的身份证,套用了他的身份,就可以通过这个身份转移财产、修改财物的属性。但Rust为了避免多人同时修改数据,除了胡七能修改财物,这时候连张三也是个木头人了,自己都无权去改变自己的财物。而胡七知道自己随时要修改财物,也不允许任何其他人来查看,以防看到的信息随后就被改变而失效。这种情况一直延续到胡七放弃这个身份,财物才返还给张三。
另外,张三可以把自己的财物转让给别人周八,这时候张三的身份下就没有财物了。如果再想通过张三获取财物信息,就会出错。注意和以上借用情况的区别,前面是财物的所有权一直归张三所有,而此处,是所有权已经到了周八手中。
------以上比喻仅限于此处所述情节,至于现实中的诸多无关因素请忽略------
这就所有权的概念,内存上的数据就像财物,只能有一个人真正拥有(现实生活中就算两个人拥有一套房,也得按比例分配),财物可以转让,共享信息,也可以借出去。对借用者来说,可以借来一个观看权,这个权并不是所有权,也可以借来所有权,这时候财物是其他人不能访问的。
此外,再加上时间这个维度!
张三从出生到挂了,是他的一个生命周期。出生后的某个时间点拥有了财物,相当于给张三的身份做了值初始化,有了实际的数据。如果有人借用他的身份,无论是只读引用(李四)还是可变引用(胡七),都必须在张三有了数据之后才能借用。张三在挂的时候,他名下的所有的财物都要销毁,所以在张三消失之前,李四胡七等人要先把借用销账(要么改而指向其他活着的人,要么自杀)。
张三的财物被周八拥有后,张三就恢复了两袖清风的状态,相当于变量又变为未初始化状态。Rust中,未初始化的变量只能赋新值,是不能直接使用的。
一、
let mut Zhang_San = "1套房产".to_string();
//创建变量Zhang_San,并用字符串初始化,这个字符串的所有者是Zhang_San
//------------------------------------------------------------
二、
let mut Zhang_San = "1套房产".to_string();
Zhang_San += "1台车";
//Zhang_San声明的时候用了mut关键字,可以修改这个字符串
//------------------------------------------------------------
三、
let mut Zhang_San = "1套房产".to_string();
Zhang_San += "1台车";
let Li_Si = &Zhang_San;
//这时候,Li_Si用只读方式借用了Zhang_San,Zhang_San和Li_Si都可以访问字
符串,但都不能更改,数据的所有权还是归Zhang_San
//------------------------------------------------------------
四、
let mut Zhang_San = "1套房产".to_string();
Zhang_San += "1台车";
let Li_Si = &Zhang_San;
let Wang_Wu = &mut Zhang_San;
//创建了可变引用后,所有其他的引用全部失效,如果后面代码再使用Li_Si,程序会
出错。此时Zhang_San拥有所有权,但是不能使用,只能使用Wang_Wu访问和修改
//------------------------------------------------------------
五、
let mut Zhang_San = "1套房产".to_string();
Zhang_San += "1台车";
let Li_Si = &Zhang_San;
let Wang_Wu = &mut Zhang_San;
let Hu_Qi = Zhang_San;
//Hu_Qi把Zhang_San的所有权拿走,现在Zhang_San以及所有Zhang_San的引用全
部不能再用。这叫做所有权的移动(Move)。