Rust中何时应使用引用而非转移所有权?
Rust所有权:从纯函数式语言视角的理解
作为从Haskell、Idris这类默认值不可变的语言转过来的开发者,刚接触Rust的所有权模型时,确实会有不少需要适应的地方——毕竟我们之前几乎不用考虑“值的归属权”这种问题。结合《Rust编程书籍》里所有权章节的内容,我来梳理下非可复制值在函数间传递的核心逻辑:
1. 转移所有权(Move)
- 当你把一个非可复制值(比如
String)传递给函数时,默认就是转移所有权。 - 举个直观的例子:
fn take_ownership(s: String) { println!("拿到的字符串:{}", s); } fn main() { let s = String::from("hello"); take_ownership(s); // 这里再尝试用s会直接编译报错,因为所有权已经被转移走了 // println!("还能用吗?{}", s); // 取消注释就会看到错误 } - 核心特点:原作用域的变量在转移后就彻底失去了这个值的使用权,如果之后还想用,必须让函数把值返回回来,比如:
fn give_back_ownership(s: String) -> String { s } fn main() { let s = String::from("hello"); let s = give_back_ownership(s); println!("拿回来继续用:{}", s); // 这里就完全没问题了 }
2. 借用(引用)
如果不想转移所有权,还能通过引用来传递值,这相当于“借”用一段临时的使用权,原作用域依然牢牢握着所有权:
- 不可变引用:用
&T表示,同一时间可以有多个不可变引用,完全不影响原变量的后续使用。fn borrow_immutable(s: &String) { println!("借来看一眼:{}", s); } fn main() { let s = String::from("hello"); borrow_immutable(&s); println!("借完了我还能用:{}", s); // 完全正常 } - 可变引用:用
&mut T表示,同一时间只能有一个可变引用,而且不能和不可变引用同时存在——这是Rust保证内存安全的关键规则之一。fn borrow_mutable(s: &mut String) { s.push_str(", world"); } fn main() { let mut s = String::from("hello"); borrow_mutable(&mut s); println!("借去改了改:{}", s); // 输出 "hello, world",原变量依然可用 }
对于我们这些习惯了纯函数式语言的人来说,Rust的所有权模型确实是个全新的概念——毕竟在Haskell或Idris里,值默认不可变,我们不用操心谁拥有它、会不会被修改,而Rust把这些细节暴露出来,虽然一开始有点绕,但正是这种设计让它在保证内存安全的同时不用GC,这点还是挺有意思的。
内容的提问来源于stack exchange,提问作者MaiaVictor
相关产品推荐
相关产品推荐

