首页 > 解决方案 > 使用复制和克隆来修复“使用移动值”是否昂贵?

问题描述

我有一个minus导致use of moved value: 'scalar'编译错误的函数,这是有道理的。

struct Point<T> {
    x: T,
    y: T,
    z: T,
}

impl<T: Sub<Output = T>> Point<T> {
    //subtract scalar value from all Point fields.
    fn minus(self, scalar: T) -> Self {
        Point {
            x: self.x - scalar,
            y: self.y - scalar,
            z: self.z - scalar,
        }
    }
}

解决方案 1

使类型可T克隆。它解决了这个问题,但它似乎是非常昂贵的操作,因为它正在复制每个字段的标量值。还有其他更便宜的解决方案吗?

impl<T: Sub<Output = T> + Clone> Point<T> {
    fn minus(self, scalar: T) -> Self {
        Point {
            x: self.x - scalar.clone(),
            y: self.y - scalar.clone(),
            z: self.z - scalar.clone(),
        }
    }
}

尝试的解决方案 2

我想也许我可以使用参考。但后来我得到cannot subtract '&T' from '&T'了,我不明白。

有没有更有效的方法来做到这一点而不是输入值CloneCopyscalar

impl<T: Sub<Output=T>> Point<T> {
    fn minus(self, scalar: &T) -> Self {
        Point {
            x: &self.x - scalar,
            y: &self.y - scalar,
            z: &self.z - scalar,
        }
    }
}

标签: rust

解决方案


要减去Copy或者Clone你需要限制你的元素可以通过引用减去,即&T - &T。您可以通过使用更高级别的 trait bound进行约束来做到这一点。(这显示在@trentcl 提供的链接中)

impl<T> Point<T>
where
    for<'a> &'a T: Sub<Output = T>,
{
    fn minus(&self, scalar: &T) -> Self {
        Point {
            x: &self.x - scalar,
            y: &self.y - scalar,
            z: &self.z - scalar,
        }
    }
}

数学运算符的实现至少应该有可用的按引用,即使按值对基本Copy类型来说更方便和可读。

Copy或是否Clone昂贵取决于是什么T,但由于这是一个通用上下文,因此您应该尽可能避免复制或克隆,以便在昂贵的情况下避免成本。如果不可能,Rust 会强制您添加Copy/Clone约束,以便调用者知道该值可能被复制,并可以判断这是否合适。


推荐阅读