首页 > 解决方案 > 获取对 Vec 元素的可变引用或创建新元素并获取该引用

问题描述

我有一个Vec<State>列表,想要搜索一个元素并获得对它的可变引用。如果它不存在,则应创建一个新的默认元素并将其添加到列表中:

struct State {
    a: usize,
}

fn print_states(states: &Vec<State>) {
    for state in states {
        print!("State{{a:{}}} ", state.a);
    }
    println!();
}

fn main() {
    let mut states = vec![State { a: 1 }, State { a: 2 }, State { a: 3 }];

    print_states(&states);

    let mut state = match states.iter_mut().find(|state| state.a == 2) {
        Some(state) => state,
        None => {
            let new_state = State { a: 3 };
            states.push(new_state);
            states.last().unwrap()
        }
    };
    state.a = 4;
    drop(state);
    print_states(&states);
}

这将导致:

error[E0594]: cannot assign to `state.a` which is behind a `&` reference
  --> src/main.rs:25:5
   |
17 |     let mut state = match states.iter_mut().find(|state| state.a == 2) {
   |         --------- help: consider changing this to be a mutable reference: `&mut State`
...
25 |     state.a = 4;
   |     ^^^^^^^^^^^ `state` is a `&` reference, so the data it refers to cannot be written

问题是None路径。在None => panic!()不创建这个新的默认元素的情况下使用时,我可以修改找到的元素

我需要改变什么才能使这项工作?

标签: rustreferencemutable

解决方案


你的问题是state.last().unwrap()-line。.last()on方法Vec返回 a &State,这会导致编译器推断为的类型(state可以将-case 中的 the 强制转换为)。这就是为什么你不能在第 28 行更改。&State&mut StateSome()state

将行更改为state.last_mut().unwrap()andstate将是 a&mut State而不是&State。您的示例在此之后编译。


推荐阅读