重载Add-operator而不复制操作数

时间:2016-10-28 09:16:28

标签: rust

我正在Rust中编写一个应用程序,它必须集中使用向量算法,我偶然发现了为结构类型设计运算符重载的问题。

所以我有一个类似的矢量结构:

struct Vector3d {
    pub x: f64,
    pub y: f64,
    pub z: f64,
}

我希望能够写出类似的内容:

let x = Vector3d {x:  1.0, y: 0.0, z: 0.0};
let y = Vector3d {x: -1.0, y: 0.0, z: 0.0};

let u = x + y;

据我所知,有三种不同的方法可以做到:

  1. 直接为std::ops::Add实施Vector3d个特征。这是有效的,但这个特征的方法签名是:

    fn add(self, other: Vector3d)
    
  2. 因此它会在使用后使其参数无效(因为它会移动它们),这在我的情况下是不可取的,因为许多矢量将用于多个表达式。

    1. Add实施Vector3d特征,并实施Copy特征。这是有效的,但我觉得如果因为Vector3d不是一个轻量级的东西(至少24个字节)可以快速复制,特别是当有很多调用算术函数时。

    2. 按照建议here实施AddVector3d的引用。这是有效的,但为了应用运算符,我将不得不写

      let u = &x + &y;
      
    3. 我不喜欢这种表示法,因为它看起来并不完全等同于数学,只是u = x + y

      我不确定哪种变体是最佳的。所以,问题是:有没有办法以这样的方式重载'+'运算符

      1. 它接受其参数作为参考,而不是复制或移动它们;
      2. 它只允许u = x + y代替u = &x + &y吗?

1 个答案:

答案 0 :(得分:6)

  

是否有办法以“

”的方式重载“+”运算符      
      
  1. 它接受其参数作为参考,而不是复制或移动它们;
  2.   
  3. 它只允许u = x + y代替u = &x + &y
  4.   

,没有办法做到这一点。 Rust非常重视显性,并且很难在类型之间自动转换。

但是,问题的解决方案很简单:只是#[derive(Copy)] 。我可以向你保证,24字节不是很多。如今,计算机喜欢立即处理大量数据而不是处理少量数据。

除此之外,Copy并不是关于复制/克隆的性能开销:

  

只需复制位即可复制的类型(即memcpy)。

later in the documentation

  

一般来说,如果您的类型可以实现Copy,那么它应该。

您的类型Vector3d只需复制位即可复制,因此应实现Copy(只需#[derive()])。

性能开销是另一个问题。如果你有一个类型可以(并因此)实现Copy,但你仍然认为类型太大(再次:24个字节不是!),你应该设计所有方法他们接受参考文献的方式(这并不容易;请阅读Matthieu的评论)。这还包括Add impl。如果你想通过引用将某些东西传递给函数,程序员应该明确地写它。这就是Rust的哲学所说的。