- 区别于自行管理内存的以及自带GC的语言。rust 通过管理权管理堆内存。
所有权规则
- 每一个值都有一个被称为所有者(owner)的变量。
- 值在任何时刻都只有一个所有者。
- 当所有者(变量)离开作用域,这个值将会被丢弃。
变量作用域
- 作用域是一项 item 在程序中的有效范围。全局作用域以及
{}
内的作用域。 - 离开作用域时
rust
, 自动调用drop
函数。
移动
- 栈上不可变变量的拷贝直接拷贝值(移动)。
- 非字面量字符串的拷贝,拷贝的是
String
的头信息,即存储字符串实际内存指针、长度、和容量信息的数据,并不是拷贝实际的堆上字符串数据。 移动
:为避免二次释放当堆上引用数据被拷贝赋值后原值将会无效,如下:
|
|
- Rust 永远也不会自动创建数据的 “深拷贝”。因此,任何 自动 的复制可以被认为对运行时性能影响较小。
克隆
- 与移动相反,克隆会实际拷贝堆上数据。
|
|
- 一个类型(栈上数据)被
Copy trait
注解,一个旧的变量在将其赋值给其他变量后仍然可用。 - Rust 不允许自身或其任何部分实现了
Drop trait
的类型使用Copy trait
。 - 任何简单标量值的组合可以是
Copy
的,不需要分配内存或某种形式资源的类型是Copy
的,如下: -
- 所有整数类型,比如 u32。
-
- 布尔类型,bool,它的值是 true 和 false。
-
- 所有浮点数类型,比如 f64。
-
- 字符类型,char。
-
- 元组,当且仅当其包含的类型也都是 Copy 的时候。比如,(i32, i32) 是 Copy 的,但 (i32, String) 就不是。
所有权和函数
- 将值传递给函数在语义上与给变量赋值相似。向函数传递值可能会移动或者复制。
- 变量进入和离开作用域的示例:
|
|
返回值和作用域
- 演示返回值转移所有权:
|
|
- 将值(非copy变量值)赋给另一个变量时移动它。
- 当持有堆中数据值的变量离开作用域时,其值将通过 drop 被清理掉,除非数据被移动为另一个变量所有。
引用与借用
- 引用:以变量的引用进行赋值或者传参不会转移变量的所有权。
|
|
- 使用
&
引用相反的操作是 解引用(dereferencing)
,它使用解引用运算符,*
。 - 获取引用作为函数参数称为
借用
。
|
|
- 要修改引用变量必须用
mut
关键字定义变量可变并且定义引用可变:
|
|
- 在特定作用域中的特定数据只能有一个可变引用。这个主要是为了在编译期就避免数据竞争的出现。
|
|
- 同样,也不能在拥有不可变引用的同时拥有可变引用。避免不可变引用受到可变引用的未知影响。
- 一个引用的作用域从声明的地方开始一直持续到最后一次使用为止。
|
|
悬垂引用
- 指针的内存被释放,但是指针还存在的情况。
|
|
- 同时只能存在一个可变引用或者同时只能存在多个不可变引用。
- 引用必须总是有效的。
slice
- 引用一个集合中的一段连续序列。如
[0..5]
引用开始到第6个元素,等同于[..5]
,同样[1..]
引用第二到结尾,[..]
引用整个字符串。 - 字符串字面值本身是一个 slice 。