我现在面临Rust的借用问题,我有一个想法来解决它。但我认为我发现的方式不是一个好的答案。所以我想知道是否有另一种解决方法。
我使用以下示例代码来描述我的情况:
struct S {
val: u8
}
impl S {
pub fn f1(&mut self) {
println!("F1");
self.f2(self.val);
}
pub fn f2(&mut self, input: u8) {
println!("F2");
// Do something with input
}
}
fn main() {
let mut s = S {
val: 0
};
s.f1();
}
结构S
有一个方法f2
,它需要额外的参数input
来执行某些操作。还有另一种方法f1
,它使用结构f2
的{{1}}调用val
。对于不同的用例,局外人可以拨打S
或f1
。
当我编译上面的代码时,我收到以下错误消息:
f2
我大致了解Rust的借用是如何运作的。所以我知道我可以通过将src\main.rs:9:17: 9:25 error: cannot use `self.val` because it was mutably borrowed [E0503]
src\main.rs:9 self.f2(self.val);
^~~~~~~~
src\main.rs:9:9: 9:13 note: borrow of `*self` occurs here
src\main.rs:9 self.f2(self.val);
^~~~
的实现更改为:
f1
但是,我觉得这个解决方案有点多余。我想知道是否有办法解决这个问题而不使用额外的变量绑定。
答案 0 :(得分:3)
您的解决方案不是因为额外的变量绑定,而是因为额外的副本。可以隐式复制整数类型,因此let v = self.val
会创建值的副本。该副本不是从self
借来的,而是拥有的。因此,编译器允许您使用此副本调用f2
。
如果你写self.f2(self.val)
,编译器也会尝试复制self.val
。但是,在此位置无法进行复制,因为函数调用借用self
。因此,除非您复制之前的值,否则无法进行此类调用。这不是语法限制,而是借用检查器的强制执行。无论如何,最好按照实际发生的顺序编写复制和调用。
如果您尝试用作参数的类型不是Copy
(例如String
),则需要编写let v = self.val.clone(); self.f2(v);
以明确询问编译器的副本。不允许进行此类调用而不进行复制。您可能需要使该方法不可变或以某种方式消除该参数。
答案 1 :(得分:1)
您可以将此技巧用于可复制值:
pub fn f1(&mut self) {
println!("F1");
match self.val {x => self.f2(x)};
}
但是,使用显式临时变量更加明确和惯用。