欢迎光临散文网 会员登陆 & 注册

所有权

2021-08-19 01:22 作者:707才不会沉迷B站  | 我要投稿

写程序不可避免要管理内存,而内存管理是非常容易出错的,有的语言使用垃圾回收机制,有的靠开发者自己管理。垃圾回收会降低执行效率,开发者自己管理对开发要求很高。Rust突破限制,使用独有的所有权机制解决内存管理问题。

所有权与堆栈关系密切。栈和堆使用效率是有区别的,栈是有序的,所以使用起来更快。堆是随机存储的,跳跃存取肯定要比顺序存取慢。变量存入栈时必须知道大小,而堆可以不确定大小,分配一块足够大的内存区域即可。可是分配时需要寻找一块足够大的块,这就要花费些时间。

所有权有三个特点:

  1. 每个变量都有他的所有者

  2. 所有者同时只有一个

  3. 所有者出了作用域就会释放变量

以String为例,String大小是变化的,所以是在运行时分配的,并且需要申请堆内存,堆内存的申请是通过from方法,申请之后的释放往往是关键。有些语言通过gc控制,自动回收;有些没有gc的语言需要手动释放;rust则是通过在作用域结束自动调用drop方法来释放的。

Move:

下面的代码中x和y的值都是5,而且都存储在栈上,实际上是栈上有两个5,y=x的时候复制了一个到栈上,所以有两个,而不是同时指向一个。

对于复杂类型,也就是数据存储在堆中的类型,复制的只是栈上的内容,并不复制堆中的内容。

s1在栈中存储了指向堆的指针、字符串长度和可存储容量。赋值时,s2复制了s1的栈信息,指向与s1相同的堆内存,然后s1会失效。相当于将堆内存从s1移动到了s2,所以赋值操作称为移动。移动=浅拷贝+失效旧变量。

如果想要实现深拷贝,也就是堆数据也被拷贝,则使用clone方法即可。

标量类型,占用的内存大小是确定的,存储在栈中的,默认都是实现了clone特性的,深拷贝与浅拷贝是相同的。包含标量类型的tuple默认也实现了clone,如(i32, i32)实现了,(i32, String)没实现。

实现了drop特性的类型不能再实现clone。

对于函数的入参和返回参数都是和赋值操作类似的,也会有变量的move操作。

当堆中的变量离开作用域时,会调用drop,但是如果变量move了,失去了所有权就不会调drop了。

如果除了返回move参数外,想返回多个附加数据,那么一种方法是可以用tuple来传递。


所有权的评论 (共 条)

分享到微博请遵守国家法律