声明变量
let
可变性
默认不可变
mut 修饰可变
变量遮蔽(shadowing)
Rust 允许声明相同的变量名,在后面用let声明的相同名称的变量会遮蔽掉前面声明的
类型
- 基本类型
- 复合类型
基本类型
- 数值类型: 有符号整数 (i8, i16, i32, i64, isize)、 无符号整数 (u8, u16, u32, u64, usize) 、浮点数 (f32, f64)、以及有理数、复数
- 字符串:字符串字面量和字符串切片 &str
- 布尔类型: true和false
- 字符类型: 表示单个Unicode字符,存储为4个字节
- 单元类型: 即 () ,其唯一的值也是 ()
复合类型
- 字符串与切片
- 元组 tup
- 结构体 struct
- 枚举 enum
- 数组
语句和表达式()
表达式结尾没有";",总要返回值
let x = x + 1; // 语句
let y = y + 5; // 语句
x + y // 表达式
函数
- 用fn关键字定义一个函数
- 用return或最后一条表达式作为函数返回值
- 无返回值的函数会隐式返回一个 ()
- 作函数返回类型的时候,表示该函数永不返回
内存管理的3种机制
- 垃圾回收机制(GC),在程序运行时不断寻找不再使用的内存,典型代表:Java、Go
- 手动管理内存的分配和释放, 在程序中,通过函数调用的方式来申请和释放内存,典型代表:C++
- 通过所有权来管理内存,编译器在编译时会根据一系列规则进行检查,典型代表:Rust
所有权
- 每个值都只能有一个所有者(变量)
- 每个值同时只能有一个所有者
- 所有者(变量)离开作用域范围时,这个值将被丢弃(free),Rust 会自动调用 drop 函数并清理变量的内存
stack & heap
stack存储已知且固定大小的内存空间的数据,快, 如基本类型
heap存储大小未知或者可能变化的数据,慢,如struct
对比:入栈比在堆上分配内存要快,栈数据往往可以直接存储在 CPU 高速缓存中,而堆数据只能存储在内存中。访问堆上的数据比访问栈上的数据慢,因为必须先访问栈再通过栈上的指针来访问内存。处理器处理和分配在栈上数据会比在堆上的数据更加高效
所有权与堆栈
- 当你的代码调用一个函数时,传递给函数的参数(包括可能指向堆上数据的指针和函数的局部变量)依次被压入栈中,当函数调用结束时,这些值将被从栈中按照相反的顺序依次移除。
- 因为堆上的数据缺乏组织,因此跟踪这些数据何时分配和释放是非常重要的,否则堆上的数据将产生内存泄漏 —— 这些数据将永远无法被回收。这就是 Rust 所有权系统为我们提供的强大保障。
move
- 浅拷贝,只拷贝stack上的内容,指针指向的内容不拷贝
let s1 = String::from("rust");
let s2 = s1;
println!("{}, world!", s1);
move
- 浅拷贝( shallow copy ),只拷贝stack上的内容,指针指向的内容不拷贝
- 任何自动的复制都是浅拷贝
- 浅拷贝发生在stack上
克隆(深拷贝)
- 首先,Rust 永远也不会自动创建数据的 “深拷贝”。因此,任何自动的复制都不是深拷贝,可以被认为对运行时性能影响较小。
- 如果我们确实需要深度复制 String 中堆上的数据,而不仅仅是栈上的数据,可以使用一个叫做 clone 的方法。
let s1 = String::from("rust");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
函数传值与返回
- 将值传递给函数,一样会发生 移动 或者 复制
借用(Borrowing)
- 获取变量的引用
- 和go 、c 一样
- 函数参数类型签名变化,eg: String => &String
- 允许你使用值,但是不获取所有权
- 默认是不可变引用,当引用离开作用域后,其指向的值也不会被丢弃
- 可变引用加mut:&mut
- 同一作用域,特定数据只能有一个可变引用,可以多个不变引用
- 引用的作用域 s 从创建开始,一直持续到它最后一次使用的地方,这个跟变量的作用域有所不同,变量的作用域从创建持续到某一个花括号 }
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
// 新编译器中,r1,r2作用域在这里结束
let r3 = &mut s;
println!("{}", r3);
} // 老编译器中,r1、r2、r3作用域在这里结束
// 新编译器中,r3作用域在这里结束
- 同一时刻,你只能拥有要么一个可变引用, 要么任意多个不可变引用
- 引用必须总是有效的