MST

星途 面试题库

面试题:Rust函数参数引用中的借用规则冲突处理

假设你有一个函数`fn process_data<'a>(data1: &'a mut Vec<i32>, data2: &'a Vec<i32>)`,在函数内部,你需要同时对`data1`进行修改并读取`data2`的部分数据,但编译器提示借用规则冲突。请分析冲突原因并给出至少两种解决方案。
29.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

冲突原因分析

在Rust中,借用规则规定同一时间内,对于一个可变引用(&mut),不能有其他任何引用(可变或不可变)存在。在process_data函数中,data1是可变引用,data2是不可变引用。当试图在修改data1的同时读取data2时,就违反了这个规则,因为可变引用独占访问权,不允许同时存在不可变引用。

解决方案

  1. 拆分操作: 将对data1的修改操作和对data2的读取操作分开,先进行读取,然后再进行修改。
fn process_data<'a>(data1: &'a mut Vec<i32>, data2: &'a Vec<i32>) {
    // 先读取data2
    let value_from_data2 = data2[0];
    // 然后修改data1
    data1.push(value_from_data2);
}
  1. 使用CellRefCell: 对于data2,如果其内部结构允许,可以使用CellRefCell来绕过编译时的借用检查,实现内部可变性。这里以RefCell为例:
use std::cell::RefCell;

fn process_data<'a>(data1: &'a mut Vec<i32>, data2: &'a RefCell<Vec<i32>>) {
    let value_from_data2 = data2.borrow()[0];
    data1.push(value_from_data2);
}

调用时需要将data2RefCell包裹:

fn main() {
    let mut data1 = vec![1, 2, 3];
    let data2 = RefCell::new(vec![4, 5, 6]);
    process_data(&mut data1, &data2);
}
  1. 使用索引和迭代器: 利用迭代器在不同阶段分别处理data1data2,避免同时借用冲突。
fn process_data<'a>(data1: &'a mut Vec<i32>, data2: &'a Vec<i32>) {
    let mut iter1 = data1.iter_mut();
    let iter2 = data2.iter();
    for (mut item1, item2) in iter1.by_ref().zip(iter2) {
        *item1 += *item2;
    }
    for item1 in iter1 {
        *item1 *= 2;
    }
}