(十一)Rust 所有权规则、内存和分配

所有权规则

1.每个值都有一个变量,这个变量是该值的所有者

2.每个值同时只能有一个所有者

3.当所有者超出作用域的时候,该值将被删除

变量作用域

作用域就是程序中一个项目的有效范围,例子:

String类型

为了演示一些所有权的相关规则,需要一个稍微复杂一点的数据类型,因为String类型比之前那些基础标量数据类型复杂一些,这里只讲String与所有权相关的部分

字符串字面值就是程序里写死的字符串值,虽然方便,但是不能满足所有的需求场景,原因之一就是因为字符串字面值是不可变的,另一个原因就是所有的字符串值都能在编写代码时确定,就比如获取用户的输入并保存,相对这种情况,Rust 提供了第二种字符串类型:String类型

String类型会在堆上来分配自己所需的存储空间,而且能存储在编译时未知大小的文本。

创建String类型的值

可以使用from函数从字符串字面值创建出String类型

如:let s = String::from("hello"); 

两个冒号“::”表示from时String类型下的函数,这类字符串是可以被修改的,例子:

为什么String类型的值可以修改,而字符串字面值不能修改,因为它们处理内存的方式不同

内存和分配

字符串字面值,在编译时就知道它的内容,其文本内容直接被硬编码到最终的可执行文件里,因为不可变,所以速度快、高效。

String类型为了支持可变性,需要在堆上分配内存来保存编译时未知的文本内容,所以操作系统必须在运行时来请求内存,这一步是通过调用String::from来实现

当用完String之后,需要使用某种方式将内存返回给操作系统,在拥有GC的语言中,GC会跟踪并清理不再使用的内存,比如JAVA,C#。没有GC的话,就需要我们去识别内存何时不再使用,并调用代码将它们返回,如果忘了,那就浪费内存,如果提前做了,那变量会非法,如果做了两次,就会出现严重的bug,针对没有GC的语言,都必须每做一次分配,对应一次释放

Rust采用了不同的方式,对于某个值来说,当拥有它的变量走出作用域时,内存会立即自动交还给操作系统

drop函数

当变量走出作用域后,Rust会自动调用drop函数来释放

变量和数据交互的方式:移动(Move)

多个变量可以与同一个数据使用一种独特的方式进行交互,如: let x = 5;   let y = x; 整数是已知且固定大小的简单的值,这两个5会被压到栈中

let s1 = String::from("hello");   let s2 = s1;  这个虽然跟上面的例子很相似,但它们的运行方式是完全不一样的

一个String由3个部分组成:

ptr:一个指向存放字符串内容的内存的指针

len:长度,就是存放字符串内容所需的字节数

capacity:容量,是指String从操作系统总共获得内存的总字节数

这些东西是放在栈中,而存放字符串内容的部分则是在堆上

当把s1赋给s2时,String的数据被复制了一份:在栈上复制了一份指针。长度。容量。但并没有复制指针所指向的堆上的数据

变量离开作用域时Rust会自动调用drop函数,并将变量使用的堆内存释放,当s1和s2离开作用域的时候,它们都会尝试释放相同的内存,就会引起严重的bug:二次释放

为了保证内存安全,Rust没有尝试复制被分配的内存,Rust的做法是让s1失效,这时,就算s1离开作用域的时候,Rust也不需要释放任何东西

如果当s2创建后,再使用s1的话,会报错:

可能你会将复制指针、长度、容量视为浅拷贝,但由于Rust让s1失效了,所以这里用一个新的术语:移动(Move),相当于s1移动到了s2,既然只有s2是有效的,那就只有s2离开自己的作用域时释放内存空间,就避免了二次释放,这就体现了Rust的安全性

克隆

如果真想对堆上面的String数据进行深度拷贝,而不仅仅时栈上的数据,可以使用clone克隆方法,这个以后会细说,现在只是举一个简单的例子:

  • 30
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值