变量
变量默认是不可改变的。不过可变性也是非常有用的。变量只是默认不可变;正如在第二章所做的那样,你可以在变量名之前加 mut
来使其可变。除了允许改变值之外,mut
向读者表明了其他代码将会改变这个变量值的意图。
1 | fn main() { |
通过let来shadowing之前的变量。mut
与隐藏的另一个区别是,当再次使用 let
时,实际上创建了一个新变量,我们可以改变值的类型,但复用这个名字。
1 | let x = if condition { |
所有权(系统)是 Rust 最为与众不同的特性,它让 Rust 无需垃圾回收(garbage collector)即可保障内存安全
一些语言中具有垃圾回收机制,在程序运行时不断地寻找不再使用的内存;在另一些语言中,程序员必须亲自分配和释放内存。Rust 则选择了第三种方式:通过所有权系统管理内存,编译器在编译时会根据一系列的规则进行检查。在运行时,所有权系统的任何功能都不会减慢程序
堆和栈
栈中的所有数据都必须占用已知且固定的大小
在编译时大小未知或大小可能变化的数据,要改为存储在堆上
所有权规则:
- Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
- 值有且只有一个所有者。
- 当所有者(变量)离开作用域,这个值将被丢弃。
浅拷贝(shallow copy)和 深拷贝(deep copy),那么拷贝指针、长度和容量而不拷贝数据可能听起来像浅拷贝。不过因为 Rust 同时使第一个变量无效了,这个操作被称为 移动(move)和克隆(clone)
1 | let s1 = String::from("hello"); |
上述代码error,禁止无效的引用
哪些类型可以浅拷贝
那么什么类型是 Copy
的呢?可以查看给定类型的文档来确认,不过作为一个通用的规则,任何简单标量值的组合可以是 Copy
的,不需要分配内存或某种形式资源的类型是 Copy
的。如下是一些 Copy
的类型:
- 所有整数类型,比如
u32
。 - 布尔类型,
bool
,它的值是true
和false
。 - 所有浮点数类型,比如
f64
。 - 字符类型,
char
。 - 元组,当且仅当其包含的类型也都是
Copy
的时候。比如,(i32, i32)
是Copy
的,但(i32, String)
就不是。
不变引用和可变引用
1 | fn main() { |
可变引用有一个很大的限制:在特定作用域中的特定数据有且只有一个可变引用
用大括号,标明作用域
关于作用域部分,有很大的技巧,也就是声明和使用部分的之间?
1 | let s = String::from("hello world"); |