所有权
所有权(系统)是 Rust 最为与众不同的特性,它让 Rust 无需垃圾回收(garbage collector)即可保障内存安全。
所有运行的程序都必须管理其使用计算机内存的方式。一些语言中具有垃圾回收机制,在程序运行时不断地寻找不再使用的内存;在另一些语言中,程序员必须亲自分配和释放内存。Rust 则选择了第三种方式:通过所有权系统管理内存,编译器在编译时会根据一系列的规则进行检查。在运行时,所有权系统的任何功能都不会减慢程序。
所有权规则
- Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
- 值有且只有一个所有者。
- 当所有者(变量)离开作用域,这个值将被丢弃。
Move
浅拷贝和深拷贝
Rust 有一个叫做 Copy
trait 的特殊注解,可以用在类似整型这样的存储在栈上的类型上(第十章详细讲解 trait)。如果一个类型拥有 Copy
trait,一个旧的变量在将其赋值给其他变量后仍然可用。Rust 不允许自身或其任何部分实现了 Drop
trait 的类型使用 Copy
trait。
将值传递给函数在语义上与给变量赋值相似。向函数传递值可能会移动或者复制,就像赋值语句一样。
变量的所有权总是遵循相同的模式:将值赋给另一个变量时移动它。当持有堆中数据值的变量离开作用域时,其值将通过 drop
被清理掉,除非数据被移动为另一个变量所有。
引用与借用
对象的引用不会获取值的所有权
我们将获取引用作为函数参数称为 借用
在特定作用域中的特定数据有且只有一个可变引用,这个限制的好处是 Rust 可以在编译时就避免数据竞争。数据竞争(data race)类似于竞态条件,它可由这三个行为造成:
- 两个或更多指针同时访问同一数据。
- 至少有一个指针被用来写入数据。
- 没有同步数据访问的机制
当拥有某值的不可变引用时,就不能再获取一个可变引用。
在 Rust 中编译器确保引用永远也不会变成悬垂状态:当你拥有一些数据的引用,编译器确保数据不会在其引用之前离开作用域。
Slices
slice 允许你引用集合中一段连续的元素序列,而不用引用整个集合。
start..end
语法代表一个以 start
开头并一直持续到但不包含 end
的 range。如果需要包含 end
,可以使用 ..=
而不是 ..
“字符串 slice” 的类型声明写作 &str
结构体
创建一个实例需要以结构体的名字开头,接着在大括号中使用 key: value
键-值对的形式提供字段,其中 key 是字段的名字,value 是需要存储在字段中的数据值。实例中字段的顺序不需要和它们在结构体中声明的顺序一致。
Rust 并不允许只将某个字段标记为可变。
参数名与字段名都完全相同,可以使用字段初始化简写语法
结构体更新语法,eg:
let user2 = User {
email: String::from("xxx@example.com"),
username: String::from("xxxx"),
..user1
};
使用没有命名字段的元组来创建结构体,eg: struct Color(i32, i32, i32);
没有任何字段的类单元结构体(),即unit类型,类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用。
使用 {:#?}
替换 println!
字符串中的 {:?},使得结构体的打印更易读。
定义结构体上的方法:
impl 结构体名 {
函数
}
impl
块的另一个有用的功能是:允许在 impl
块中定义 不 以 self
作为参数的函数。这被称为 关联函数(associated functions),因为它们与结构体相关联。
结构体可以有多个impl块
派生trait,#[derive(debug)]
枚举与模式匹配
枚举可以将数据直接放进每一个枚举成员,eg:
enum IpAddr {
V4(String),
V6(String),
}
每个成员可以处理不同类型和数量的数据, eg:
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
可以在枚举上定义方法
标准库 定义的枚举Option,表示存在或不存在
match 控制流运算符
match 后面跟一个任意类型的表达式 而 if 只能是bool类型
匹配是穷尽的
_通配符
if let 简单控制流
包、crate 与模块
- 包(Packages)是 Cargo 的一个功能,它允许你构建、测试和分享 crate。
- Crates 是一个模块的树形结构,它形成了库或二进制项目。
- 模块(Modules)和 use 关键字允许你控制作用域和路径的私有性。
- 路径(path)是一个命名例如结构体、函数或模块等项的方式
模块系统包括以下内容:
- 模块,一个组织代码和控制路径私有性的方式
- 路径,一个命名项(item)的方式
use
关键字用来将路径引入作用域pub
关键字使项变为公有as
关键字用于将项引入作用域时进行重命名- 使用外部包
- 嵌套路径用来消除大量的
use
语句 - 使用 glob 运算符将模块的所有内容引入作用域
- 如何将不同模块分割到单独的文件中
pub use 重导出