Rust基础之所有权机制

主流语言常见的内存管理方式主要是两种:
1.程序员手动分配和释放内存,比如C/C++等
2.垃圾回收系统, 比如JAVA,C#,GO等

而Rust语言的内存管理方式与上述两种内存管理方式都不同,Rust使用的是所有权机制。

所有权系统

所有权规则

在这里插入图片描述

当值的所有者离开作用域以后,这个值所占的内存就会被释放。编译器会自动检查每个所有者的作用域,当所有者离开作用域时,编译器会自动加上释放内存的操作。 所有者离开作用域后就立刻释放,而不是像垃圾回收器那样有延迟的释放内存。

在实际写代码的时候要遵循这3条规则。

所有权相关概念与操作

变量作用域

在这里插入图片描述

所有权变更

在这里插入图片描述

1.所有权移动

复制操作会将一个变量的所有权移动给新的变量,比如:
let a = 1;
let b = a;
则, 值 1 的所有权移动到了变量b,a不再拥有 1 的所有权。

在这里插入图片描述

len<=capacity

在这里插入图片描述
图 4-2:变量 s2 的内存表现,它有一份 s1 指针、长度和容量的拷贝

这个表现形式看起来 并不像 图 4-3 中的那样,如果 Rust 也拷贝了堆上的数据,那么内存看起来就是这样的。如果 Rust 这么做了,那么操作 s2 = s1 在堆上数据比较大的时候会对运行时性能造成非常大的影响。

在这里插入图片描述
图 4-3:另一个 s2 = s1 时可能的内存表现,如果 Rust 同时也拷贝了堆上的数据的话

之前我们提到过当变量离开作用域后,Rust 自动调用 drop 函数并清理变量的堆内存。不过图 4-2 展示了两个数据指针指向了同一位置。这就有了一个问题:当 s2 和 s1 离开作用域,他们都会尝试释放相同的内存。这是一个叫做 二次释放(double free)的错误,也是之前提到过的内存安全性 bug 之一。两次释放(相同)内存会导致内存污染,它可能会导致潜在的安全漏洞。

为了确保内存安全,这种场景下 Rust 的处理有另一个细节值得注意。与其尝试拷贝被分配的内存,Rust 则认为 s1 不再有效,因此 Rust 不需要在 s1 离开作用域后清理任何东西。看看在 s2 被创建之后尝试使用 s1 会发生什么;这段代码不能运行:

let s1 = String::from("hello");
let s2 = s1;

println!("{}, world!", s1);

你会得到一个类似如下的错误,因为 Rust 禁止你使用无效的引用。

error[E0382]: use of moved value: `s1`
 --> src/main.rs:5:28
  |
3 |     let s2 = s1;
  |         -- value moved here
4 |
5 |     println!("{}, world!", s1);
  |                            ^^ value used here after move
  |
  = note: move occurs because `s1` has type `std::string::String`, which does
  not implement the `Copy` trait

如果你在其他语言中听说过术语 浅拷贝(shallow copy)和 深拷贝(deep copy),那么拷贝指针、长度和容量而不拷贝数据可能听起来像浅拷贝。不过因为 Rust 同时使第一个变量无效了,这个操作被称为 移动(move),而不是浅拷贝。上面的例子可以解读为 s1 被 移动 到了 s2 中。那么具体发生了什么,如图 4-4 所示。
在这里插入图片描述
图 4-4:s1 无效之后的内存表现

这样就解决了我们的问题!因为只有 s2 是有效的,当其离开作用域,它就释放自己的内存,完毕。

另外,这里还隐含了一个设计选择:Rust 永远也不会自动创建数据的 「深拷贝」。因此,任何 自动 的复制可以被认为对运行时性能影响较小。

克隆

所有权在内存中的表现形式

相关内容:
Rust学习笔记007-所有权
Rust编程语言:https://learnku.com/docs/rust-lang/2018/ch04-01-what-is-ownership/4505

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值