传递给重载的 PartialEq 的值的所有权

Ownership of values passed to overloaded PartialEq

我一直在尝试重载一些运算符。我 运行 进入了一个我不太明白的情况。在为我的结构 Value 实现特征 PartialEq 时,我注意到下面的实现有效并且不会移动值,允许我在使用 == 运算符后继续使用这些值在不将值的引用传递给运算符的情况下对它们进行处理。

另一方面,这不适用于 Neg 特征(或 AddSub 等)的实现。为了在不移动值的情况下使用 - 运算符,我必须在对 Value 结构的引用上实现 Neg 特征。

为什么我可以实现 PartialEq 特性而不必担心在不传递对值的引用时移动,但是在实现 Neg 特性时我需要担心?我是否错误地实现了 Neg 特性?我忽略了 PartialEq 特征的微妙之处吗?

这是我的代码:

struct Value {
    x: i32
}

impl PartialEq for Value {
    fn eq(&self, other: &Value) -> bool {
        if self.x == other.x {
                true
            } else {
                false
            }
    }
}
impl Eq for Value {}

impl Neg for &Value {
    type Output = Value;

    fn neg(self) -> Self::Output {
        Value {
            x: -self.x
        }
    }
}

fn main() {
    let v1: Value = Value {x: 1};
    let v2: Value = Value {x: 2};
    let equal = v1 == v2; // Not passing a reference, but also able to use v1
    let v3 = -&v1;
    let v4 = -&v1; // Works because I am passing a reference. If I change the implementation of Neg to 'impl Neg for Value' and remove the reference here and in the line above (for v3), it will complain that v1 had been moved (as expected).
}

Is there a subtlety to the PartialEq trait that I am overlooking?

PartialEq的方法引用了selfother(签名中的&selfother: &T),而Neg , Add, Sub, 等取self and (for binary operators) other by value (self and other: T in the signature) . v1 == v2 脱糖为 PartialEq::eq(&v1, &v2),而 !v1 脱糖为 Neg::neg(v1)

您可能希望 Neg 获得传递值的所有权的原因是该值是否已分配动态内存(通过 BoxVec 等)。在这种情况下,改变 self 然后 return self (或者在 Output 类型不同于Self 类型)而不是分配一个新对象(这将需要新的动态内存分配),即使原始值在操作后未被使用。

另一方面,PartialEq的方法总是return一个boolbool 不分配任何动态内存,因此按值传递参数没有任何好处。预计测试两个对象是否相等不需要改变其中一个或两个对象,因此参数是共享引用的原因。

Am I implementing the Neg trait incorrectly?

不,但您可能要考虑为 Value&Value 实现 Neg(特别是如果您正在编写供其他人使用的库)。

如果您的类型复制起来很便宜(即它很小并且不使用动态内存),请考虑实现 CloneCopy(可能通过派生它们)。这样,您可以将值传递给运算符而无需将值移动到运算符,因为值将被复制。