我有一个 Rust 程序,其中包含两个版本的结构及其方法实现。第一个版本使用函数指针,而第二个版本使用装箱特征对象。这是代码:
pub struct FnWrapper1 {
pub f: fn(&mut BoolAndFns1),
}
pub struct BoolAndFns1 {
pub b: bool,
pub fs: Vec<FnWrapper1>,
}
impl BoolAndFns1 {
pub fn meth(&mut self) {
if let Some(wrapper) = self.fs.last_mut() {
(wrapper.f)(self);
}
}
}
pub struct FnWrapper2 {
pub f: Box<dyn Fn(&mut BoolAndFns2)>,
}
struct BoolAndFns2 {
pub b: bool,
pub fs: Vec<FnWrapper2>,
}
impl BoolAndFns2 {
pub fn meth(&mut self) {
if let Some(wrapper) = self.fs.last_mut() {
(wrapper.f)(self);
}
}
}
fn main() {
let mut bf1 = BoolAndFns1 {
b: false,
fs: vec![FnWrapper1 {
f: |bf| {
bf.b = true;
},
}],
};
bf1.meth();
let mut bf2 = BoolAndFns2 {
b: false,
fs: vec![FnWrapper2 {
f: Box::new(|bf2| {
bf2.b = true;
}),
}],
};
bf2.meth();
}
当我尝试编译此程序时,Rust 编译器给出错误:
FnWrapper2
:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:30:16
|
29 | if let Some(wrapper) = self.fs.last_mut() {
| ------- first mutable borrow occurs here
30 | (wrapper.f)(self);
| ----------- ^^^^ second mutable borrow occurs here
| |
| first borrow later used by call
但是
FnWrapper1
没有错误。
因此,我有两个问题:
区别在于,函数指针确实实现了
Copy
,因此 wrapper.f
不是借用 self
。您可以通过暂时从向量中删除该函数而不是引用它来避免别名:
impl BoolAndFns2 {
pub fn meth(&mut self) {
if let Some(wrapper) = self.fs.pop() {
(wrapper.f)(self);
self.fs.push(wrapper);
}
}
}