[英]Overloading the Add-operator without copying the operands
I'm writing an application in Rust that will have to use vector arithmetic intensively and I stumbled upon a problem of designing operator overload for a structure type. 我正在Rust中编写一个应用程序,它必须集中使用向量算法,我偶然发现了为结构类型设计运算符重载的问题。
So I have a vector structure like that: 所以我有一个这样的矢量结构:
struct Vector3d {
pub x: f64,
pub y: f64,
pub z: f64,
}
and I want to be able to write something like that: 我希望能够写出类似的东西:
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;
As far as I can see, there are three different ways to do it: 据我所知,有三种不同的方法:
Implement std::ops::Add
trait for Vector3d
directly. 实现std::ops::Add
直接为Vector3d
std::ops::Add
特征。 That works, but this trait's method signature is: 这有效,但这个特征的方法签名是:
fn add(self, other: Vector3d)
So it will invalidate its arguments after usage (because it moves them) which is undesirable in my case since many vectors will be used in multiple expressions. 所以它会在使用后使它的参数无效(因为它会移动它们),这在我的情况下是不可取的,因为许多矢量将用在多个表达式中。
Implement Add
trait for Vector3d
and also implement the Copy
trait. 实现为Vector3d
Add
特征并实现Copy
特征。 This works, but I feel iffy on that since Vector3d
isn't exactly a lightweight thing (24 bytes at least) that can be copied quickly, especially when there are many calls to arithmetic functions. 这是有效的,但我觉得很Vector3d
,因为Vector3d
不是一个轻量级的东西(至少24字节),可以快速复制,特别是当有很多调用算术函数时。
Implement Add
for references to Vector3d
, as suggested here . 实施Add
了参考文献Vector3d
,如建议在这里 。 This works, but in order to apply the operator, I will have to write 这是有效的,但为了应用运算符,我将不得不写
let u = &x + &y;
I don't like this notation because it doesn't exactly looks like its mathematic equivalent, just u = x + y
. 我不喜欢这种表示法,因为它看起来不像它的数学等价物,只是u = x + y
。
I'm not sure which variant is optimal. 我不确定哪种变体是最佳的。 So, the question is: is there a way to overload the '+' operator in such a way that 所以,问题是:有没有办法以这样的方式重载'+'运算符
u = x + y
instead of u = &x + &y
? 它只允许写u = x + y
而不是u = &x + &y
? Is there a way to overload the '+' operator in such a way that 有没有办法以这种方式重载'+'运算符
- It accepts its arguments as references instead of copying or moving them; 它接受其参数作为引用,而不是复制或移动它们;
- It allows to write just
u = x + y
instead ofu = &x + &y
? 它只允许写u = x + y
而不是u = &x + &y
?
No , there is no way to do that. 不 ,没有办法做到这一点。 Rust greatly values explicitness and hardly converts between types automatically. Rust非常重视显性,并且几乎不会在类型之间自动转换。
However, the solution to your problem is simple: just #[derive(Copy)]
. 但是,问题的解决方案很简单: 只需#[derive(Copy)]
。 I can assure you that 24 bytes are not a lot. 我可以向你保证,24字节不是很多。 Computers these days love to crunch a lot of data at once instead of working on little chunks of data. 如今,计算机喜欢立即处理大量数据而不是处理少量数据。
Apart from that, Copy
is not really about the performance overhead of copying/cloning: 除此之外, Copy
并不是关于复制/克隆的性能开销:
Types that can be copied by simply copying bits (ie
memcpy
). 只需复制位即可复制的类型(即memcpy
)。
And later in the documentation : 后来在文档中 :
Generally speaking, if your type can implement
Copy
, it should. 一般来说,如果你的类型可以实现Copy
,它应该。
Your type Vector3d
can be copied by just copying bits, so it should implement Copy
(by just #[derive()]
ing it). 您可以通过复制位来复制Vector3d
类型,因此它应该实现Copy
(仅通过#[derive()]
来实现)。
The performance overhead is a different question. 性能开销是一个不同的问题。 If you have a type that can (and thus does) implement Copy
, but you still think the type is too big (again: 24 bytes aren't!), you should design all your methods in a way that they accept references (it's not that easy; please read Matthieu's comment). 如果你有一个类型可以(并因此)实现Copy
,但你仍然认为类型太大(再次:24个字节不是!), 你应该以他们接受引用的方式设计你的所有方法 (它是不那么容易;请阅读Matthieu的评论)。 This also includes the Add
impl. 这还包括Add
impl。 And if you want to pass something to a function by reference, the programmer shall explicitly write it. 如果你想通过引用将某些东西传递给函数,程序员应该明确地写它。 That's what Rust's philosophy would say anyway. 这就是Rust的哲学无论如何都会说的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.