Rust函数何时重新借用/移动参数?两种签名为何表现不同?
Rust中函数参数的重新借用与移动规则
先看示例代码:
fn main() { use std::str::FromStr; let mut my_str: String = String::from_str("hello").unwrap(); let borrow_str: &mut String = &mut my_str; foo(borrow_str); println!("{}", borrow_str) } // 可运行,触发重新借用 fn foo<T>(string: &mut T) {} // 不可运行,触发移动 // fn foo<T>(string: T) {}
两种函数签名的差异原因
1. fn foo<T>(string: &mut T) 可运行的逻辑
调用这个函数时,Rust会自动把T推断为String,因此函数参数的实际类型是&mut String,和传入的borrow_str(类型为&mut String)完全匹配。
此时Rust会执行重新借用:从原可变引用borrow_str中再生成一个新的&mut String,这个新引用的生命周期被限制在函数调用的时间段内。函数执行完毕后,新引用的生命周期结束,原borrow_str的使用权被归还,所以后续的println!可以正常调用它。
2. fn foo<T>(string: T) 不可运行的逻辑
这里T会被推断为&mut String,函数参数直接接收这个可变引用本身。由于可变引用属于非Copy类型,传递参数时会触发移动语义:borrow_str的所有权被转移到函数的string参数中,函数调用结束后,borrow_str就变成了无效变量(已被移动),后续再尝试使用它就会触发编译错误。
通用规则总结
- 当函数参数为引用类型(
&T/&mut T):传入同类型引用时,Rust会自动进行重新借用,原引用在函数调用后仍可正常使用。 - 当函数参数为所有权类型(非引用的
T):若传入值为不可Copy类型(如可变引用、String、自定义非Copy结构体等),则会发生移动,原变量在调用后无法再使用。
内容的提问来源于stack exchange,提问作者j.s.shin
相关产品推荐
相关产品推荐

