这是第一篇关于 Rust 自学的博客。今天我们将介绍 Rust 最重要的特性之一:所有权(Ownership)

所有权规则

在 Rust 中,所有权遵循以下三条基本规则:

  1. 每一个值都被一个变量所拥有,该变量被称为值的所有者
  2. 一个值同时只能被一个变量所拥有,或者说一个值只能拥有一个所有者。
  3. 当所有者(变量)离开作用域范围时,这个值将被丢弃(drop)。

栈与堆

首先讲解

  • 栈(Stack):需要确定内存的大小,一般用于小内存且固定不变的变量。
  • 堆(Heap):内存大小未知,因此适用于大内存或会改变的变量。

示例代码

1. 浅拷贝(栈上内存的直接拷贝)

1
2
let x = 5;
let y = x;

2. 引用(指针)和借用(拷贝指针)

1
2
3
4
5
fn main() {
let x: &str = "hello, world";
let y = x;
println!("{}, {}", x, y);
}

3. 克隆(深拷贝)

1
2
3
4
5
let s1 = String::from("hello");
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);
// 这里相当于为两个变量分配了独立的内存

引用和调用规则

  • 不可变变量&):只能是不可变引用(&)。
  • 可变变量&mut):可以是可变引用(&mut,也可以是不可变引用(&

注意:

  1. 同一作用域内只能有一个可变引用,但可以有多个不可变引用。
  2. 可变引用不可变引用不能同时存在。

变量内存释放

在新版本的编译器中,Rust 会自动判断变量最后一次使用的位置,并在此处释放变量内存。如果数据已被释放,指针不会被保留,编译器会报错,确保程序安全。

1
2
3
4
5
6
7
8
fn main() {
let s = String::from("hello");
let r1 = &s; // 不可变引用
let r2 = &s; // 另一个不可变引用
println!("{}, {}", r1, r2);

let r3 = &mut s; // 编译报错,不能同时存在可变引用和不可变引用
}