当前位置:首页 > Rust > 正文

深入理解Rust函数参数传递(从值传递到引用传递,掌握所有权机制)

在学习 Rust函数参数传递 时,很多初学者会感到困惑。这是因为 Rust 的内存管理模型与传统语言(如 C++ 或 Java)不同,它引入了“所有权”(Ownership)和“借用”(Borrowing)的概念。本文将用通俗易懂的方式带你一步步理解 Rust 中函数如何接收参数,以及背后的 Rust所有权 机制。

深入理解Rust函数参数传递(从值传递到引用传递,掌握所有权机制) Rust函数参数传递 Rust所有权 Rust引用传递 Rust值传递 第1张

1. 值传递(Move语义)

在 Rust 中,默认情况下,当你把一个变量作为参数传给函数时,会发生“移动”(move),而不是复制。这意味着原变量将不能再被使用。

fn main() {    let s = String::from("hello");    takes_ownership(s); // s 被 move 到函数中    // println!("{}", s); // ❌ 编译错误!s 已经无效}fn takes_ownership(some_string: String) {    println!("{}", some_string);} // some_string 离开作用域,内存被释放

上面的例子展示了 Rust值传递 的核心:一旦变量被 move,原变量就失效了。这是 Rust 防止内存重复释放(double free)的关键机制。

2. 引用传递(借用)

如果你不想转移所有权,而是想让函数临时使用数据,可以使用“引用”(&T)。这称为“借用”(borrowing)。

fn main() {    let s = String::from("hello");    let len = calculate_length(&s); // 传入 s 的引用    println!("'{}' 的长度是 {}", s, len); // ✅ s 仍然有效!}fn calculate_length(s: &String) -> usize {    s.len()} // s 是引用,离开作用域时不释放数据

注意:&s 表示“s 的引用”,而函数参数 s: &String 表示“接收一个 String 的引用”。这种方式不会转移所有权,因此调用后原变量依然可用。

3. 可变引用(Mutable Borrowing)

如果你想在函数中修改传入的数据,可以使用可变引用(&mut T)。但 Rust 有严格的规则:同一时间只能有一个可变引用,且不能同时存在不可变引用。

fn main() {    let mut s = String::from("hello");    change(&mut s); // 传入可变引用    println!("{}", s); // 输出 "hello, world"}fn change(s: &mut String) {    s.push_str(", world");}

这种设计保证了内存安全,避免了数据竞争(data race)。

4. Copy 类型的特殊行为

对于实现了 Copy trait 的类型(如 i32、bool、f64 等简单类型),Rust 会自动复制值,而不是 move。因此你可以多次使用同一个变量。

fn main() {    let x = 5;    makes_copy(x);    println!("x is still {}", x); // ✅ 没问题!i32 实现了 Copy}fn makes_copy(some_integer: i32) {    println!("{}", some_integer);}

总结

掌握 Rust引用传递Rust值传递 的区别,是理解 Rust 内存安全模型的关键。记住以下三点:

  • 默认参数传递是 move(转移所有权);
  • 使用 &T 可以借用(不转移所有权);
  • 使用 &mut T 可以可变借用(但受严格限制)。

通过合理使用这些机制,你可以在不牺牲性能的前提下写出安全、高效的 Rust 代码。希望这篇教程能帮助你彻底搞懂 Rust函数参数传递