rust所有权与借用

Rust :所有权(Ownership)

所有权是 Rust 最核心的概念之一,也是 Rust 与 Python、JavaScript、Java 等语言的重要区别。

一、什么是所有权?

Rust 的所有权(Ownership)是一套管理内存的规则。

它让 Rust 在不依赖垃圾回收器(GC)的情况下,仍然能够保证内存安全。

1. 为什么需要所有权?

程序运行时,需要使用内存存储数据。

常见语言管理内存的方式:

语言 内存管理方式
C 手动分配和释放
C++ 手动管理、RAII、智能指针
Java 垃圾回收(GC)
Python 引用计数 + 垃圾回收
JavaScript 垃圾回收(GC)
Rust 所有权 + 借用 + 生命周期

Rust 的特点是:

在编译阶段检查大部分内存使用规则,避免很多运行时内存错误。

2. 所有权的三条核心规则

必须掌握:

  1. Rust 中的每个值都有一个所有者(Owner)。
  2. 同一时刻,一个值只能有一个所有者。
  3. 当所有者离开作用域(Scope),这个值会被清理。

这里的第二条是针对普通所有权模型而言的。学习 Rc<T> 等智能指针时,还会接触共享所有权。

二、作用域(Scope)

先看最简单的代码。

1
2
3
4
5
6
7
8
fn main() {
{
let word = String::from("apple");
println!("{word}");
}

// println!("{word}"); // 编译错误
}

执行过程:

img

示意图:变量只在自己的作用域内有效。

当程序执行到内部作用域的 } 时:

  • word 离开作用域。
  • Rust 自动调用清理逻辑(对于 String,释放其拥有的堆内存)。
  • 后续不能再访问 word。

可以把作用域理解为变量的有效范围。

三、所有权转移(Move)

这是本章第一个难点。

1. 普通整数赋值

1
2
3
4
5
6
7
fn main() {
let a = 10;
let b = a;

println!("{a}");
println!("{b}");
}

输出:

1
2
10
10

为什么 a 还能使用?

因为整数 i32 实现了 Copy trait,赋值时会复制它的值。

2. String 赋值

1
2
3
4
5
6
7
fn main() {
let word1 = String::from("apple");
let word2 = word1;

println!("{word2}");
println!("{word1}"); // 编译错误
}

这里会编译失败。

原因是:

1
let word2 = word1;

将 word1 的所有权转移给了 word2。

Move 后堆中的字符串数据没有被复制,所有权交给 word2,word1 不再可用。

为什么 Rust 要这样设计?

因为 String 包含指向堆内存的指针、长度和容量。如果简单复制这些管理信息,两个变量就可能试图释放同一块内存。

Rust 通过所有权转移,避免这种问题。

四、克隆(Clone)

如果想保留两个独立的字符串怎么办?

使用 .clone()。

1
2
3
4
5
6
7
fn main() {
let word1 = String::from("apple");
let word2 = word1.clone();

println!("{word1}");
println!("{word2}");
}

输出:

1
2
apple
apple

clone() 会复制字符串数据,因此两个变量各自拥有独立的数据。

操作 所有权转移 复制字符串数据
let b = a;(String) 是 否
let b = a.clone(); 否 是
let b = a;(i32) 否 是(Copy)

注意:clone() 可能涉及堆内存分配,因此不应该为了绕开所有权问题而无脑使用。

五、借用(Borrowing)

假设你只想读取一个单词,而不想取得它的所有权。

这时可以使用引用 &。

1
2
3
4
5
6
7
8
fn main() {
let word = String::from("apple");

let borrowed_word = &word;

println!("{borrowed_word}");
println!("{word}");
}

输出:

1
2
apple
apple

这里:

  • word 拥有字符串。
  • borrowed_word 借用了字符串。
  • 所有权没有转移。

1. 函数中的借用

1
2
3
4
5
6
7
8
9
10
11
fn show_word(word: &String) {
println!("Word: {word}");
}

fn main() {
let word = String::from("apple");

show_word(&word);

println!("Original: {word}");
}

输出:

1
2
Word: apple
Original: apple

函数参数 word: &String 表示接收一个 String 的不可变引用。

实际开发中,只需要读取字符串内容时,通常更推荐使用 &str:

1
2
3
fn show_word(word: &str) {
println!("Word: {word}");
}

它既可以接收 String 的借用,也可以接收字符串字面量,使用起来更灵活。

六、可变借用(Mutable Borrowing)

普通引用只能读取,不能修改。

如果需要修改字符串,使用 &mut。

1
2
3
4
5
6
7
8
9
10
11
fn add_translation(word: &mut String) {
word.push_str(" - 苹果");
}

fn main() {
let mut word = String::from("apple");

add_translation(&mut word);

println!("{word}");
}

输出:

1
apple - 苹果

注意两个地方:

1
let mut word = String::from("apple");

声明变量可以修改。

1
add_translation(&mut word);

创建可变引用。

借用规则

Rust 对借用有严格限制:

  1. 同一时间可以存在多个不可变引用 &T。
  2. 或者存在一个可变引用 &mut T。
  3. 不能同时使用相互冲突的可变和不可变借用。
  4. 引用必须始终有效,不能悬垂。

例如:

1
2
3
4
5
6
7
8
9
10
11
fn main() {
let mut word = String::from("apple");

let r1 = &word;
let r2 = &word;

println!("{r1} {r2}");

let r3 = &mut word;
r3.push_str("!");
}

这段代码可以编译。

因为 r1 和 r2 最后一次使用结束后,才创建 r3。

Rust 的借用检查并不是简单地认为引用必须一直存在到所在代码块结束,而是会分析引用的最后使用位置。

七、函数与所有权

函数参数也会发生所有权转移。

1
2
3
4
5
6
7
8
9
10
11
fn consume_word(word: String) {
println!("{word}");
}

fn main() {
let word = String::from("apple");

consume_word(word);

// println!("{word}"); // 编译错误
}

因为 consume_word() 接收的是 String,所以调用函数时所有权发生转移。

函数执行结束后,参数 word 离开作用域,字符串会被释放。

如果函数只需要读取数据,应该优先使用引用:

1
2
3
4
5
6
7
8
9
10
11
fn show_word(word: &str) {
println!("{word}");
}

fn main() {
let word = String::from("apple");

show_word(&word);

println!("{word}");
}

另外,函数返回 String 时,也可以将所有权交给调用者:

1
2
3
4
5
6
7
8
fn create_word() -> String {
String::from("apple")
}

fn main() {
let word = create_word();
println!("{word}");
}

八、所有权知识总结

语法 含义 原变量能否继续使用
let b = a; Move(非 Copy 类型) 否
let b = a.clone(); 克隆 是
let b = &a; 不可变借用 是,受借用规则限制
let b = &mut a; 可变借用 是,借用结束后
fn f(a: String) 函数取得所有权 否
fn f(a: &str) 函数借用字符串 是
fn f(a: &mut String) 函数可变借用 是,借用结束后

rust所有权与借用
https://umeshu.cn/2026/10/21/Rust/rust所有权与借用/
作者
IchiharaYuuko
发布于
2026年10月21日
许可协议