面试题答案
一键面试冲突原因分析
在Rust中,借用规则规定同一时间内,对于一个可变引用(&mut
),不能有其他任何引用(可变或不可变)存在。在process_data
函数中,data1
是可变引用,data2
是不可变引用。当试图在修改data1
的同时读取data2
时,就违反了这个规则,因为可变引用独占访问权,不允许同时存在不可变引用。
解决方案
- 拆分操作:
将对
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);
}
- 使用
Cell
或RefCell
: 对于data2
,如果其内部结构允许,可以使用Cell
或RefCell
来绕过编译时的借用检查,实现内部可变性。这里以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);
}
调用时需要将data2
用RefCell
包裹:
fn main() {
let mut data1 = vec![1, 2, 3];
let data2 = RefCell::new(vec![4, 5, 6]);
process_data(&mut data1, &data2);
}
- 使用索引和迭代器:
利用迭代器在不同阶段分别处理
data1
和data2
,避免同时借用冲突。
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;
}
}