跳转到主要内容
模块 3 · 第 1 课(共 2)课程中的5/14~15 min
模块课程(1/2)

所有权规则

所有权是 Rust 最独特的特征。它允许语言保证内存安全,而不需要垃圾收集器或强制您手动释放堆内存(如 C 或 C++ 中)。

所有权的三大规则

Rust 中的内存管理由编译器严格检查的三个简单规则控制:

  1. Rust 中的每个值都有一个称为其所有者的变量。
  2. 一次只能有一位所有者。
  3. 当所有者超出范围时,该值将自动删除。

堆栈与堆

要了解所有权,了解数据所在位置很重要:

  • 堆栈:存储编译时已知的固定大小的数据(例如整数、布尔值)。访问速度非常快。
  • 堆:存储编译时未知的动态大小数据(例如,String)。分配速度较慢,并且需要一个存储在堆栈上的指针。

“动”的概念

当我们将一个堆分配的变量分配给另一个变量时,Rust 移动(或转移)该值的所有权,从而使第一个变量无效:

Rust
let s1 = String::from("ciao");
let s2 = s1; // Ownership of the text moves to s2. s1 is NO longer usable!

// println!("{}", s1); // COMPILATION ERROR! s1 is "borrow of moved value"
println!("{}", s2); // Valid!

此行为避免了“双重释放错误”(在超出范围时尝试释放相同的内存两次),因为只有 s2 会释放内存。

“克隆”(深拷贝)的概念

如果我们明确需要复制 String 的全部内容(堆栈指针和堆中的实际文本数据),我们可以使用 .clone() 方法。这完全复制了堆上的数据,保持原始变量和新变量都有效,但代价是新内存分配的性能开销:

Rust
let s1 = String::from("ciao");
let s2 = s1.clone(); // Deep copy. Both variables remain valid!
println!("s1: {}, s2: {}", s1, s2);

“复制”的概念

对于完全存储在 Stack 上的简单类型(例如整数 i32、布尔值 bool、字符 char),赋值执行实际的自动浅复制,这意味着两个变量仍然有效:

Rust
let x = 5;
let y = x; // Copies the value 5 onto the stack. Both variables are usable!
println!("x: {}, y: {}", x, y); // Valid!

自己尝试一下

锻炼#rust.m3.l1.e1
尝试:0加载中...

声明一个包含文本“hello”的字符串 s1。将 s1 分配给 s2(以便移动所有权)。最后,使用 println! 打印 s2。

正在加载编辑器...
显示提示

使用 `let s2 = s1;` 将所有权转移给 `s2` 并使用 `println!('{}', s2);` 打印它。

3 次尝试后可用的解决方案

锻炼#rust.m3.l1.e2
尝试:0加载中...

声明一个值为 5 的整型变量 x。将 x 赋值给 y(执行复制)。最后,在同一个 println 中打印 x 和 y!陈述。

正在加载编辑器...
显示提示

执行 `let y = x;`,然后打印这两个值,例如 `println!('{} {}', x, y);`。

3 次尝试后可用的解决方案

锻炼#rust.m3.l1.e3
尝试:0加载中...

Declare a String s1 with the value "Rust". Create a deep copy of s1 in a new variable s2 using the clone method. Finally, print both s1 and s2 separated by a space using the println! macro.

正在加载编辑器...
显示提示

Use `let s2 = s1.clone();` to deep copy the value of `s1` into `s2`, then print them with `println!("{} {}", s1, s2);`.

3 次尝试后可用的解决方案