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

Rust中如何在zip迭代器循环内对原类型执行可变操作?

问题:Rust中zip迭代器时修改原类型导致借用冲突

问题代码

#[derive(Default, Debug)]
struct Data {
    pub values: [bool; 4],
}
fn main() {
    let mut d = Data::default();
    println!("{:?}", d);
    
    for (i, (v, dv)) in [true, false, false, true].iter().zip(d.values.iter()).enumerate() {
        if *v != *dv {
            d.values[i] = *v;
        }
    }
    
    println!("{:?}", d);
}

编译错误

Compiling playground v0.0.1 (/playground)
error[E0506]: 无法赋值给 `d.values[_]`,因为它已被借用
  --> src/main.rs:11:13
   |
9  |     for (i, (v, dv)) in [true, false, false, true].iter().zip(d.values.iter()).enumerate() {
   |                         ------------------------------------------------------------------
   |                         |                                     |
   |                         |                                     此处借用了 `d.values[_]`
   |                         后续使用了该借用
10 |         if *v != *dv {
11 |             d.values[i] = *v;
   |             ^^^^^^^^^^^^^^^^ 对已借用的 `d.values[_]` 进行赋值

有关此错误的更多信息,请尝试 `rustc --explain E0506`。
error: 由于之前的错误,无法编译 `playground`

原因分析

Rust的借用检查规则禁止同一变量同时存在不可变借用和可变借用:

  • d.values.iter()创建了不可变迭代器,持有d.values的不可变借用,该借用在整个循环周期内有效。
  • 循环内的d.values[i] = *v尝试获取d.values的可变借用,与之前的不可变借用冲突,导致编译失败。

解决方案

方案1:直接索引遍历(无需迭代器zip)

通过索引访问两个数组,避免创建持续的借用:

#[derive(Default, Debug)]
struct Data {
    pub values: [bool; 4],
}
fn main() {
    let mut d = Data::default();
    println!("{:?}", d);
    
    let src = [true, false, false, true];
    for i in 0..src.len() {
        let v = src[i];
        if v != d.values[i] {
            d.values[i] = v;
        }
    }
    
    println!("{:?}", d);
}

方案2:使用可变迭代器直接修改(推荐)

用iter_mut()获取目标数组的可变引用迭代器,直接与源迭代器zip后修改,无需额外索引:

#[derive(Default, Debug)]
struct Data {
    pub values: [bool; 4],
}
fn main() {
    let mut d = Data::default();
    println!("{:?}", d);
    
    for (v, dv) in [true, false, false, true].iter().zip(d.values.iter_mut()) {
        if *v != *dv {
            *dv = *v;
        }
    }
    
    println!("{:?}", d);
}

这种方式符合Rust迭代器的设计风格,无需手动处理索引,同时避免了借用冲突。

方案3:复制目标数组(适用于小型Copy类型)

利用数组的Copy特性,复制目标数组到循环中,避免持有原数组的借用:

#[derive(Default, Debug)]
struct Data {
    pub values: [bool; 4],
}
fn main() {
    let mut d = Data::default();
    println!("{:?}", d);
    
    let src = [true, false, false, true];
    for (i, (&v, dv)) in src.iter().zip(d.values).enumerate() {
        if v != dv {
            d.values[i] = v;
        }
    }
    
    println!("{:?}", d);
}

内容的提问来源于stack exchange,提问作者RobotHerder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:47:32