模块课程(1/2)
所有权规则
所有权是 Rust 最独特的特征。它允许语言保证内存安全,而不需要垃圾收集器或强制您手动释放堆内存(如 C 或 C++ 中)。
所有权的三大规则
Rust 中的内存管理由编译器严格检查的三个简单规则控制:
- Rust 中的每个值都有一个称为其所有者的变量。
- 一次只能有一位所有者。
- 当所有者超出范围时,该值将自动删除。
堆栈与堆
要了解所有权,了解数据所在位置很重要:
- 堆栈:存储编译时已知的固定大小的数据(例如整数、布尔值)。访问速度非常快。
- 堆:存储编译时未知的动态大小数据(例如,
String)。分配速度较慢,并且需要一个存储在堆栈上的指针。
“动”的概念
当我们将一个堆分配的变量分配给另一个变量时,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() 方法。这完全复制了堆上的数据,保持原始变量和新变量都有效,但代价是新内存分配的性能开销:
let s1 = String::from("ciao");
let s2 = s1.clone(); // Deep copy. Both variables remain valid!
println!("s1: {}, s2: {}", s1, s2);“复制”的概念
对于完全存储在 Stack 上的简单类型(例如整数 i32、布尔值 bool、字符 char),赋值执行实际的自动浅复制,这意味着两个变量仍然有效:
let x = 5;
let y = x; // Copies the value 5 onto the stack. Both variables are usable!
println!("x: {}, y: {}", x, y); // Valid!自己尝试一下
声明一个包含文本“hello”的字符串 s1。将 s1 分配给 s2(以便移动所有权)。最后,使用 println! 打印 s2。
显示提示
使用 `let s2 = s1;` 将所有权转移给 `s2` 并使用 `println!('{}', s2);` 打印它。
3 次尝试后可用的解决方案
声明一个值为 5 的整型变量 x。将 x 赋值给 y(执行复制)。最后,在同一个 println 中打印 x 和 y!陈述。
显示提示
执行 `let y = x;`,然后打印这两个值,例如 `println!('{} {}', x, y);`。
3 次尝试后可用的解决方案
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 次尝试后可用的解决方案