又一个 Rust 所有权教程

发布: (2025年12月11日 GMT+8 17:02)
5 min read
原文: Dev.to

Source: Dev.to

在 Rust 中最重要的概念之一是所有权(ownership)和借用(borrowing)。大量文章专门讨论这个细分主题;本教程尝试通过示例来解释该概念。

所有权是一套规则,决定 Rust 程序如何管理内存。Rust 使用所有权系统并在编译期进行检查;如果违反任何规则,程序将无法编译,并且没有运行时开销。

所有权是什么?

对所有权的初体验

Java 版

public void own(String text) {}

public static void main(String[] args) {
    var text = "my text";
    own(text);
    System.out.println(text);
}

Rust 翻译

fn own(_: String) {}

fn main() {
    let text: String = String::from("my text"); // 1
    own(text);
    println!("{}", text);
}

编译器报错:

error[E0382]: borrow of moved value: `text`
 --> src/main.rs:11:20
  |
9 |     let text: String = String::from("my text");
  |         ---- move occurs because `text` has type `String`, which does not implement the `Copy` trait
10|     own(text);
  |         ---- value moved here
11|     println!("{}", text);
  |                    ^^^^ value borrowed here after move
...
help: consider cloning the value if the performance cost is acceptable
10|     own(text.clone());

own 函数取得了 text 的所有权,因此之后不能再使用 text

Clone 与 Copy

如果我们遵循编译器的建议:

fn own(text: String) {}

fn main() {
    let text = String::from("my text");
    own(text.clone()); // 深拷贝
    println!("{}", text);
}

String 实现了 Clone,会创建一次深拷贝。这会使该值的内存使用翻倍。

当一个类型同时实现了 Copy 时,值会隐式复制,我们无需调用 clone()

#[derive(Debug, Copy, Clone)]
struct Dummy {}

fn own(_: Dummy) {}

fn main() {
    let dummy = Dummy {};
    own(dummy);               // 自动复制
    println!("{:?}", dummy); // 仍然可以使用
}

注意: 为大型结构体实现 Copy 可能会消耗大量内存,因为每一次移动都会产生一次复制。

通过引用传递

传递值会移动所有权。若想让函数借用该值,需要使用 & 传递引用:

#[derive(Debug)]
struct Dummy {}

fn borrow(_: &Dummy) {}

fn main() {
    let dummy = Dummy {};
    borrow(&dummy);          // 借用,而非移动
    println!("{:?}", dummy); // 仍然可以使用
}

通过引用读取字段:

#[derive(Debug)]
struct Dummy {
    foo: String,
}

fn borrow(dummy: &Dummy) {
    println!("{:?}", dummy.foo);
}

fn main() {
    let dummy = Dummy { foo: String::from("Foo") };
    borrow(&dummy);
    println!("{:?}", dummy); // Dummy { foo: "Foo" }
}

修改数据

在没有 mut 的情况下尝试修改

#[derive(Debug)]
struct Dummy {
    foo: String,
}

fn main() {
    let dummy = Dummy { foo: String::from("Foo") };
    dummy.foo = String::from("Bar"); // 错误
}

编译错误:

error[E0594]: cannot assign to `dummy.foo`, as `dummy` is not declared as mutable
 --> src/main.rs:8:5
  |
8 |     dummy.foo = String::from("Bar");
  |     ^^^^^^^^^ cannot assign
  |
help: consider changing this to be mutable
7 |     let mut dummy = Dummy { foo: String::from("Foo") };

将变量声明为可变

#[derive(Debug)]
struct Dummy {
    foo: String,
}

fn main() {
    let mut dummy = Dummy { foo: String::from("Foo") };
    dummy.foo = String::from("Bar");
}

通过值参数进行修改

#[derive(Debug)]
struct Dummy {
    foo: String,
}

fn mutate(mut dummy: Dummy) {
    dummy.foo = String::from("Bar");
    println!("{:?}", dummy.foo);
}

fn main() {
    let dummy = Dummy { foo: String::from("Foo") };
    mutate(dummy);
}

通过可变引用进行修改

#[derive(Debug)]
struct Dummy {
    foo: String,
}

fn mutate(dummy: &mut Dummy) {
    dummy.foo = String::from("Bar");
    println!("Inside: {:?}", dummy.foo);
}

fn main() {
    let mut dummy = Dummy { foo: String::from("Foo") };
    mutate(&mut dummy);
    println!("Outside: {:?}", dummy.foo);
}

小结

目标实现方式
获取所有权按值传递
复制值实现 Clone 并调用 clone()
自动复制值实现 Copy(隐含实现 Clone
借用(只读)传递引用 &T
修改局部变量将其声明为 mut
通过引用修改使用 &mut T 并将绑定声明为 mut

最初发表于 A Java Geek(2025 年 12 月 7 日)

Back to Blog

相关文章

阅读更多 »

我在 Rust 的第一周学到的东西

如何学习 Rust?一些常被引用的 Rust 学习资源包括:- The Rust Programming Language https://doc.rust-lang.org/stable/book/ – 官方 Rust 书籍。

JavaScript 中的对象

什么是对象? - 对象是一种可以容纳多个变量的变量。 - 它是键‑值对的集合,每个键都有对应的值。 - 组合……