如何将 `Option<&mut ...>` 传递给多个函数调用而不会导致移动错误?
How to pass `Option<&mut ...>` to multiple function calls without causing move errors?
既然可以传递对向量的可变引用(而不会引起移动),那么 Option<reference>
如何在不引起借用检查错误的情况下多次传递给函数?
这个简单的例子只是展示了当 Option<&mut Vec<usize>>
被多次传递给一个函数时会发生什么:
fn maybe_push(mut v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
if let Some(ref mut v) = v_option.as_mut() {
for i in 0..10 {
v.push(i);
c += i;
}
}
return c;
}
fn maybe_push_multi(v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
c += maybe_push(v_option);
c += maybe_push(v_option);
c += maybe_push(None);
return c;
}
fn main() {
let mut v: Vec<usize> = vec![];
let v_option = Some(&mut v);
println!("{}", maybe_push_multi(v_option));
}
报错:
error[E0382]: use of moved value: `v_option`
--> <anon>:17:21
|
16 | c += maybe_push(v_option);
| -------- value moved here
17 | c += maybe_push(v_option);
| ^^^^^^^^ value used here after move
|
= note: move occurs because `v_option` has type `std::option::Option<&mut std::vec::Vec<usize>>`, which does not implement the `Copy` trait
如果您不想将 Option
移入函数中,您也可以通过引用传递它。
fn maybe_push(mut v_option: &mut Option<&mut Vec<usize>>) -> usize
// ...
maybe_push_twice(&mut v_option);
然后替换:
maybe_push(None);
与:
maybe_push(&mut None);
您可以使用 match
表达式解构 Option
,然后为函数的每次调用创建一个新的 Option
值 maybe_push()
:
fn maybe_push_twice(v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
match v_option {
Some(v) => {
c += maybe_push(Some(v));
c += maybe_push(Some(v));
}
None => {
c += maybe_push(None);
c += maybe_push(None);
}
};
return c;
}
这里有一个更方便的方法:
fn maybe_push_twice(mut v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
c += maybe_push(v_option.as_mut().map(|x| &mut **x));
c += maybe_push(v_option);
return c;
}
您可以使用特征而不是宏:
trait RefMut<T> {
fn ref_mut(&mut self) -> Option<&mut T>;
}
impl<'t, T> RefMut<T> for Option<&'t mut T>{
#[inline]
fn ref_mut(&mut self) -> Option<&mut T>{
self.as_mut().map(|x| &mut**x)
}
}
fn maybe_push_twice(mut v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
c += maybe_push(v_option.ref_mut());
c += maybe_push(v_option);
return c;
}
既然可以传递对向量的可变引用(而不会引起移动),那么 Option<reference>
如何在不引起借用检查错误的情况下多次传递给函数?
这个简单的例子只是展示了当 Option<&mut Vec<usize>>
被多次传递给一个函数时会发生什么:
fn maybe_push(mut v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
if let Some(ref mut v) = v_option.as_mut() {
for i in 0..10 {
v.push(i);
c += i;
}
}
return c;
}
fn maybe_push_multi(v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
c += maybe_push(v_option);
c += maybe_push(v_option);
c += maybe_push(None);
return c;
}
fn main() {
let mut v: Vec<usize> = vec![];
let v_option = Some(&mut v);
println!("{}", maybe_push_multi(v_option));
}
报错:
error[E0382]: use of moved value: `v_option`
--> <anon>:17:21
|
16 | c += maybe_push(v_option);
| -------- value moved here
17 | c += maybe_push(v_option);
| ^^^^^^^^ value used here after move
|
= note: move occurs because `v_option` has type `std::option::Option<&mut std::vec::Vec<usize>>`, which does not implement the `Copy` trait
如果您不想将 Option
移入函数中,您也可以通过引用传递它。
fn maybe_push(mut v_option: &mut Option<&mut Vec<usize>>) -> usize
// ...
maybe_push_twice(&mut v_option);
然后替换:
maybe_push(None);
与:
maybe_push(&mut None);
您可以使用 match
表达式解构 Option
,然后为函数的每次调用创建一个新的 Option
值 maybe_push()
:
fn maybe_push_twice(v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
match v_option {
Some(v) => {
c += maybe_push(Some(v));
c += maybe_push(Some(v));
}
None => {
c += maybe_push(None);
c += maybe_push(None);
}
};
return c;
}
这里有一个更方便的方法:
fn maybe_push_twice(mut v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
c += maybe_push(v_option.as_mut().map(|x| &mut **x));
c += maybe_push(v_option);
return c;
}
您可以使用特征而不是宏:
trait RefMut<T> {
fn ref_mut(&mut self) -> Option<&mut T>;
}
impl<'t, T> RefMut<T> for Option<&'t mut T>{
#[inline]
fn ref_mut(&mut self) -> Option<&mut T>{
self.as_mut().map(|x| &mut**x)
}
}
fn maybe_push_twice(mut v_option: Option<&mut Vec<usize>>) -> usize {
let mut c = 0;
c += maybe_push(v_option.ref_mut());
c += maybe_push(v_option);
return c;
}