当一个类型是 `Copy` 时,方法应该移动 (`self`) 还是借用 (`&self`) 该类型?

huangapple go评论65阅读模式
英文:

When a type is `Copy` should a method move (`self`) or borrow (`&self`) the type?

问题

在Rust中,当一个类型是Copy时,方法应该使用移动 (self) 还是借用 (&self) 该类型?

对于非Copy类型的方法调用,使用移动 (self) 和借用 (&self) 之间存在显著的差异。例如,你不能调用两次使用移动 (self) 的方法。然而,对于Copy类型,至少对于调用者来说,使用移动 (self) 和借用 (&self) 之间的差异变得不那么显著。

此外,由于Rust将自动进行解引用或借用以查找方法,你可以以完全相同的方式调用使用移动 (self) 方法或引用 (&self) 方法。

我预计这两种方法之间没有太大的区别。当由Rust编译器内联时,两者似乎生成相同的汇编代码,至少从Godbolt编译器资源管理器上的我的实验来看是这样。但是,当不内联时,生成的汇编代码可能会有所不同。这只是一个微不足道的示例,因此应该持谨慎态度。

我无法从标准库中找到一个常见的做法,因为似乎有两种做法的示例。

我认为在现实世界中,每种方法之间应该没有太大的区别,尽管这确实让我感到好奇。每当我在类型上实现Copy时,我都会思考最佳方法是什么……

我找到了一个示例,在这个示例中,我必须同时为值和引用实现From,否则示例将无法编译。我相信还有许多其他表现出类似行为的示例,这可能使为移动 (self) 或借用 (&self) 实现方法更加可取。

你认为哪种方法最好?这重要吗?是否有一种标准方法?还有其他我应该考虑的情况吗?

编辑:目前,我更倾向于在Copy类型上使用移动 (self)。

英文:

In Rust, when a type is Copy, should a method move (self) or borrow (&self) the type?

When a method from a non-Copy type is called, there is a significant difference between a move (self) and a borrow (&self). For example, you would not be able to call a method that uses move (self) twice. However, for a Copy type, the difference between a move (self) and a borrow (&self) becomes less significant, at least for the caller.

In addition, as Rust will automatically dereference or borrow to look up a method, you can call a move (self) method or a reference (&self) method in the exact same manner.

I expect that there is little difference in each approach. When inlined by the Rust compiler, both appear to generate identical assembly code. At least from my experiment on the Godbolt compiler explorer. However, when not inlined the assembly code generated can be different. This is a trivial example, and therefore it should be taken with a grain of salt.

I couldn't establish a common practice from the standard library as there appears to be examples of both.

I don't think there should be much difference between each approach in the real world, although it does make me curious. Every time I implement Copy on a type, I wonder what the best approach is...

I did find an example, whereby I must implement From for both a value and a reference, otherwise the example will not compile. I am sure there are many more examples that exhibit similar behaviour, which may therefore make it more desirable to implment methods for either move (self) or borrow (&self).

What do you think is best? Does it matter? Is there a standard approach? Are there other cases that I should consider?

EDIT: At the moment I prefer to use a move (self) for Copy types.

答案1

得分: 2

以下是翻译好的部分:

我的经验法则是:

  • 如果在非Copy类型上实现时,该方法将消耗self,那么对于Copy类型,也应该采用相同的方式,因为这样更清晰和更一致。一个例子是Duration上的算术方法,例如checked_add()

  • 如果不是这样,那么对于小型类型(当一台机器字节(最多usize)明显很小时,而且通常情况下两个字节也很小,因为它们是成对传递的寄存器,但三个字节已经很大,因为它们在堆栈上传递),它们预计在未来版本中仍然很小,那么采用按值传递self,因为这样速度更快;对于其他类型(大型或可能变得大型的类型),采用&self,因为采用self将强制进行复制,速度会(在某种程度上)较慢。

    第一种类型的示例是整数、浮点数和字符的所有方法(好吧,几乎所有方法,由于遗留原因,某些char方法采用&self)。第二种类型的示例是DurationIpAddr上的方法。

From是另一回事;为拥有的对象和引用都实现它是有意义的。

英文:

My rule of thumb is:

  • If, when implementing on a non-Copy type, this method will consume self, do the same for Copy types, because it is clearer and more uniform this way. An example of this is the arithmetic methods on Duration, e.g. checked_add().

  • If not, then: for small types (when one machine bytes (up to usize) is definitely small, and two are usually small because they're passed in pair of registers, but three are already big because they're passed on stack) that are expected to stay small in future versions, take self by value because it is faster this way; for other types (big or that may become big) take &self, because taking self will force a copy and will be (somewhat) slower.

    An example of the first type is all methods on integers and floats and chars (well, almost all of them, some in char take &self for legacy reasons). An example of the second type is methods on Duration or IpAddr.

From is a different story; it makes sense to implement it for both owned and references.

huangapple
  • 本文由 发表于 2023年6月15日 08:13:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76478317.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定