You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确提取代码至函数并避免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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 17:27:33