我有一个带有两个向量的结构,该结构在Arc<Mutex<TwoArrays>>
中通过函数传递。
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>) {
let mut f = foo.lock().unwrap();
//Loop A: compiles
for i in 0..f.a.len() {
for j in 0..f.b.len() {
f.b[j] += f.a[i];
}
}
//Loop B: does not compile
for i in f.a.iter() {
for j in 0..f.b.len() {
f.b[j] += i;
}
}
}
当我创建一个使用迭代器的循环,并在其中编写另一个循环(循环B)时,编译器会抱怨:
error[E0502]: cannot borrow `f` as mutable because it is also borrowed as immutable
循环A编译。
f.b
的可变借用和f.a
的可变借用?TwoArrays
时为什么没有发生这种情况?仅当我以Arc<Mutex<TwoArrays>>
答案 0 :(得分:4)
解开LockResult
时,您会得到MutexGuard
,直接得到TwoArrays
会不是。您可以像使用TwoArrays
一样使用它,因为它实现了Deref
和DerefMut
。
当您尝试编写2个循环时,尝试同时使用deref
和deref_mut
:这是不可能的:
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>) {
let mut f = foo.lock().unwrap();
//Loop B: does not compile
for i in f.a.iter() {
// ^~~~~~~~~~~~~~~~~~~ Implicit call to `deref` here.
for j in 0..f.b.len() {
// ^~~~~~~~~~~~ Another implicit call to `deref` here.
f.b[j] += i;
// ^~~~~~~~~~~~~~~~~~~~ Implicit call to `deref_mut` here.
}
}
}
如果您在执行循环之前deref_mut
一次,则一切正常:
use std::{sync::{Arc, Mutex}, ops::DerefMut};
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(foo: &mut Arc<Mutex<TwoArrays>>) {
let mut mutex_guard = foo.lock().unwrap();
let real_two_arrays = mutex_guard.deref_mut();
for i in &mut real_two_arrays.a {
for j in &real_two_arrays.b {
*i += *j;
}
}
}
答案 1 :(得分:1)
您可以使用以下结构访问两个向量:
use std::mem;
#[derive(Debug)]
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: TwoArrays) {
let a = foo.a.clone();
let mut b = foo.b.clone();
for i in a.iter() {
let mut index = 0;
for _j in b.iter_mut() {
let mut new_value = i.clone() + foo.b[index as usize].clone();
mem::swap(&mut foo.b[index as usize], &mut new_value);
index = index + 1;
}
}
println!("Arrays A: {:?}", &foo.a);
println!("Arrays A: {:?}", &foo.b);
}
fn main() {
let a = vec![1i32, 2i32, 3i32];
let b = vec![4i32, 5i32, 6i32];
let two_arrays = TwoArrays { a, b };
// let foo = Arc::new(Mutex::new(two_arrays));
add_arrays(two_arrays);
}
为什么f会有不可变的借位?
因为您尝试使用iter()
而不是iter_mut()
进行迭代
为什么当我直接传递TwoArrays时没有发生这种情况?仅当我将其作为
传递时才会发生Arc<Mutex<TwoArrays>>
您可以将其作为裸结构传递,而无需使用示例代码使用Arc<Mutex<>>
。
如果您坚持使用Arc<Mutex<>>
通过原子引用传递相同的对象,则可以将函数签名更改为以下内容:
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>)
您需要lock()
并通过以下操作从Arc
获取该引用:
let foo = foo.lock().unwrap();