运营商超载"无法摆脱借来的内容"

Pau*_*rth 8 rust

当使用具有运算符重载的类时,我从简单的辅助方法获得编译错误.这是一个独立的测试(从我的真实代码简化,但仍然证明了问题):

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
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)

我已经阅读了Rust Book,以及关于所有权和借来的部分.我在StackOverflow上已经阅读了很多关于这个问题的问题,例如:

无法摆脱借来的内容

我不认为我自己的问题是重复的,因为虽然错误是相同的,但情况是不同的.此外,如果我知道其他问题是如何适用于这个问题,我也不必问.:-)

所以我的问题是:我该如何解决这个错误?我并不想改变&selfself,因为这会导致其他问题.

除了解决问题之外,我还想知道Rust害怕什么.我没有看到任何危险.

Fra*_*gné 8

你是在实现运营商Money而不是&Money.这意味着运营商将获得其操作数的所有权.因此,在total执行添加时,您必须移动self.absolute,这是不允许的,因为您无法移出借来的指针(您只能移动您拥有的值).如果类型实现,Rust将复制Copy(对于诸如i32或的原语就是这种情况f64); 否则,它会移动它们,这意味着移动后源将无法使用.

如果你的Money结构实际上只包含一个cents字段,我建议你实现它Copy(这也需要实现Clone,即使你没有实现,这也是一个好主意Copy).您可以实现CopyClone使用容易#[derive]:

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Money {
    cents: i64,
}
Run Code Online (Sandbox Code Playgroud)

现在,Rust不会total移动self.absolute,而是会复制它.如果无法实现Copy,则替换self.absoluteself.absolute.clone().


如果您已经实现了运算符&Money,那么您可以只传递对Money值的引用.例如,使用这样的实现,total可以像这样实现:

pub fn total(&self, basis: Money) -> Money {
    &self.absolute + &(self.percent * &basis)
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

669 次

最近记录:

9 年,7 月 前