2024开源操作系统训练营第一阶段总结-黄文轩
本文是对OS训练营第一阶段的总结,重点谈谈在第一阶段学习Rust的过程中,印象比较深刻的一些知识点。
所有权
所有权是Rust中一个非常重要的特性,查看如下代码:
1 | fn main() { |
执行let s2=s1
语句后,s1就不能再使用了,也就是说s1将资源移动给了s2,原来的变量就不再用原先的值了。Rust明确了所有权的概念,如果一个变量拥有了一个资源的所有权,就要负责那个资源的回收和释放,主要目的是为了安全。
在使用函数时,也同样要注意:
1 | fn foo(s: String) { |
在第一次使用foo时,s1字符串的所有权就移动到了参数s上,在该函数回收栈空间时,这个字符串就被回收掉了,因此无法再打印这个字符串。
如下代码就不存在问题,因为foo将所有权转移出来:
1 | fn foo(s: String) -> String { |
但是上述代码将所有权转移出来,有时还是麻烦了点,频繁转移所有权会显得很冗余,可以使用引用这个特性。
下述代码使用了引用:
1 | fn foo(s: &String) { |
Box智能指针
如果一个变量,存的是另一个变量在内存的地址值,那么就被称为指针。普通指针是对值的借用,而智能指针通常拥有对数据的所有权,可以做一些额外操作,比如管理引用计数和资源自动回收。
标准库中常见的智能指针:
Box<T>
:在堆内存上分配值Rc<T>
:启用多重所有权的引用计数类型Ref<T>
&RefMut<T>
,通过RefCell<T>
访问:在运行时而不是编译时强制借用规则的类型
本文着重介绍Box,即指向堆内存的智能指针,允许在堆上存储数据而非栈,没有其他性能开销。
常用场景:在编译时,某类型的大小无法确定。但使用该类型时,上下文却要知道它的确切大小。
1 | fn main() { |
在变量 b
在离开作用域时,同样会被释放。
同样可以作用于结构体:
1 | struct Point { |
在创建Point结构体时,其尺寸是固定的,所以它的实例会被创建在栈上。而在创建 Box<Point>
实例的时候会发生所有权转移:资源从栈上移动到了堆,原来栈的那片资源被置为无效。
可以对Box进行解引用,由于u8具有copy语义,所以解引用后,原来的boxed还能使用
1 | fn main() { |
但是对于move语义的类型来说,就不适用了
Box同样可以作为函数参数:
1 |
|