如何正确提取代码至函数并避免Rust中的值移动错误
Rust中提取大型结构体操作函数的正确方式
问题背景
我有一个大型结构体(比如Vec<i32>),原本的代码如下:
fn main() { let mut arr = vec![0, 1, 2]; // 大量前置代码 arr.push(5); // 大量后置代码 println!("{:?}", arr); }
我想把push相关的逻辑提取到独立函数里,改写为:
fn main() { let mut arr = vec![0, 1, 2]; my_push(arr, 5); println!("{:?}", arr); } fn my_push(mut arr: Vec<i32>, x: i32) { // 大量代码 arr.push(x); // 大量代码 }
但运行时触发了所有权错误:
error[E0382]: borrow of moved value: `arr` --> src/main.rs:4:22 | 2 | let mut arr = vec![0, 1, 2]; | ------- move occurs because `arr` has type `Vec<i32>`, which does not implement the `Copy` trait 3 | my_push(arr, 5); | --- value moved here 4 | println!("{:?}", arr); | ^^^ value borrowed here after move
错误原因是arr被移动到my_push函数后会被销毁,请问该如何正确实现这种代码提取?
解决方案
方法一:使用可变借用(推荐)
直接传递Vec的可变引用给函数,不会转移所有权,函数内部可直接修改原对象:
fn main() { let mut arr = vec![0, 1, 2]; my_push(&mut arr, 5); println!("{:?}", arr); // 输出 [0, 1, 2, 5] } fn my_push(arr: &mut Vec<i32>, x: i32) { // 大量代码 arr.push(x); // 大量代码 }
原理:&mut Vec<i32>是可变借用,函数仅临时获得修改原对象的权限,所有权仍保留在main函数中,调用结束后原arr依然可用。
方法二:返回修改后的结构体
如果不想使用引用,可以让函数接收结构体,修改后返回,再在调用处重新赋值:
fn main() { let mut arr = vec![0, 1, 2]; arr = my_push(arr, 5); println!("{:?}", arr); // 输出 [0, 1, 2, 5] } fn my_push(mut arr: Vec<i32>, x: i32) -> Vec<i32> { // 大量代码 arr.push(x); // 大量代码 arr }
原理:arr被移动到函数后,执行完会把修改后的Vec返回,重新赋值给原变量名相当于收回所有权。Rust编译器会通过NRVO优化消除不必要的拷贝,性能不会受太大影响。
选择建议
- 优先使用可变借用:无需额外所有权转移,逻辑清晰且性能更优。
- 仅当函数需要完全接管结构体所有权(比如后续要执行其他所有权相关操作)时,再考虑返回结构体的方式。
内容的提问来源于stack exchange,提问作者tardis3
相关产品推荐
相关产品推荐

