第二章(上):所有权 (Ownership) —— 内存管理的“第三条路”

Unknown Author 独酌
2025-11-17 Rust

准备好了吗?我们要进入 Rust 最核心、也是最难 的概念了。

在编程世界里,管理内存通常只有两种流派:

  1. 手动挡 (C/C++): 你自己分配 (malloc),自己释放 (free)。
  • 优点: 极快。
  • 缺点: 容易忘,导致内存泄漏;或者释放早了,导致程序崩溃。
  1. 自动挡 (JS/Java/Python): 有个叫 垃圾回收 (Garbage Collector, GC) 的东西在后台一直跑,帮你盯着不再用的内存并回收。
  • 优点: 省心,开发快。
  • 缺点: GC 运行的时候会占用资源,甚至造成程序卡顿 (Stop-the-world)。

Rust 选择了第三条路: 既没有 GC,也不用你手动 free

它靠的是 “所有权规则” (Ownership Rules)。

场景模拟:送礼物

为了理解这个,我们先看一段 JS 代码:

1
2
3
4
5
6
// JavaScript
let gift1 = { item: "Book" };
let gift2 = gift1; // 把 gift1 赋值给 gift2

console.log(gift1); // { item: "Book" }
console.log(gift2); // { item: "Book" }

在 JS 里,gift1gift2 就像两张 **只有地址的门卡,**它们都指向内存里的同一个 { item: "Book" } 对象。这完全没问题。

现在,让我们看看同样的逻辑在 Rust 里会发生什么。

1
2
3
4
5
6
7
8
// Rust
fn main() {
let gift1 = String::from("Book"); // 创建一个 String (分配在堆上)
let gift2 = gift1; // 赋值给 gift2

// 下面这行会报错!
println!("Gift 1 is: {}", gift1);
}

Rust 会告诉你:gift1 已经失效了(moved)!

这就引出了所有权的第一条规则:

任何时候,一个值只能有一个 所有者 (Owner)。

当你把 gift1 赋值给 gift2 时,Rust 认为你把这个值的“所有权”转移给了 gift2。既然 gift2 是新的主人,gift1 就变成废纸了。

思考题

既然 Rust 这么做是为了内存安全(避免两个变量同时操控同一块内存导致混乱),那么在这个例子中,如果我就想让 gift1gift2 都拥有这个 “Book” 数据的副本(也就是说,我想复印一份,而不是转让),让两个变量都能独立使用,你觉得应该怎么做?

(提示:在 JS 里如果你想深拷贝一个对象,你会怎么做?Rust 里有一个类似 clone 的概念。)

答案

1
let gift2 = gift1.clone();

这一招 clone() 就是 Rust 里的 “深拷贝” (Deep Copy)。 现在,堆内存里真的有两本书了。gift1gift2 各自拥有独立的数据,互不干扰。

  • **JS 对比:**这就像你用 JSON.parse(JSON.stringify(obj)) 或者 lodash 的 _.cloneDeep(obj) 把对象彻底复制了一份。

  • **代价:**就像在现实中复印一本书一样,clone() 是消耗资源(时间和内存)的。如果数据很大,频繁 clone 会让程序变慢。

标签:
独酌

独酌

小镇码农

相关文章