当使用具有运算符重载的类时,我从简单的辅助方法获得编译错误 . 这是一个独立的测试(从我的真实代码简化,但仍然证明了问题):
use std::ops::{Add, Sub, Neg, Mul, Div};
#[derive(Debug, Eq, PartialEq)]
pub struct Money {
cents: i64,
}
impl Money {
pub fn new(cents: i64) -> Money {
Money { cents: cents }
}
}
impl Add for Money {
type Output = Money;
fn add(self, other: Money) -> Money {
Money { cents: self.cents + other.cents }
}
}
impl Mul<Money> for f64 {
type Output = Money;
fn mul(self, rhs: Money) -> Money {
Money { cents: (self * rhs.cents as f64) as i64 }
}
}
#[derive(Debug)]
pub struct AbsOrPerc {
pub absolute: Money,
pub percent: f64,
}
impl AbsOrPerc {
pub fn new(abs: Money, perc: f64) -> AbsOrPerc {
AbsOrPerc {
absolute: abs,
percent: perc,
}
}
pub fn total(&self, basis: Money) -> Money {
// This works:
// Money::new((self.absolute.cents as f64 + self.percent * basis.cents as f64) as i64)
// This doesn't:
self.absolute + self.percent * basis
}
}
我正在尝试使用Rust 1.8编译它,但我收到此错误:
src/lib.rs:42:5: 42:9 error: cannot move out of borrowed content [E0507]
src/lib.rs:42 self.absolute + self.percent * basis
我已经阅读了Rust Book,以及关于所有权和借来的部分 . 我在StackOverflow上读到了很多关于这个问题的问题,例如:
Cannot move out of borrowed content
我不认为我自己的问题是重复的,因为虽然错误是相同的,但情况是不同的 . 此外,如果我知道其他问题是如何适用于这个问题,我也不必问 . :-)
所以我的问题是:我该如何解决这个错误?我不想将 &self
更改为 self
,因为这会导致其他问题 .
除了解决问题之外,我还想知道Rust害怕什么 . 我没有看到任何危险 .
1 回答
您正在
Money
而不是&Money
上实施运算符 . 这意味着运营商将获得其操作数的所有权 . 因此,在total
中,要执行添加,您必须移动self.absolute
,这不是一个借来的指针(您只能移动您拥有的值) . 如果它们的类型实现Copy(对于像i32
或f64
这样的基元的情况),Rust将复制值;否则,它会移动它们,这意味着移动后源将无法使用 .如果您的
Money
结构实际上只包含cents
字段,我建议您实现Copy
(这也需要实现Clone,即使您没有实现Copy
,这也是一个好主意) . 您可以使用#[derive]
轻松实现Copy
和Clone
:现在,在
total
中,Rust将复制它而不是移动self.absolute
. 如果无法实现Copy
,则将self.absolute
替换为self.absolute.clone()
.如果您已在
&Money
上实现了运算符,那么您可以只传递对Money
值的引用 . 例如,通过这样的实现,total
可以像这样实现: