2017-09-12 35 views
3

您可以实现Copy特征以赋予复制语义类型而不是移动语义。这只能在所有组成元素(产品类型的每个因子或每个总和类型变体的每个因子)都是Copy时才能完成。复制特质是否应该尽可能地实施?

这可以让你也做出相当大的类型Copy。如果该类型的大小“很大”,可以执行Copy是否会对性能造成不利影响?

如果Copy应始终执行,为何不能自动特质像SyncSend对于那些能够实现它,并有退出的语义,而不是选择在类型?

+2

[我应该什么时候应该复制?](https://doc.rust-lang.org/stable/std/marker/trait.Copy.html#when-should-my-type-be-copy) – ljedrz

回答

6

为什么[Copy]没有自动特质像SyncSend对于那些能够实现它,并有退出的语义,而不是选择在类型?

Copy曾经被实现它的类型自动实现。此行为在Rust 1.0之前不会太长,已更改in December 2014

Copy特质是否应该尽可能实施?

不一定。在开发一个库时,实现Copy或不在某种类型上的选择会影响向前兼容性。删除类型上的Copy实现是一个突破性更改(该类型的用户可能依赖于正在复制的类型而不是已移动的类型),因此,为了尊重semantic versioning,库会强加一个主要版本冲突。特别是,如果某种类型现在能够实现Copy,但您认为该类型可能会演变为不可能再执行Copy,则应该安全地玩,并且不要实施该类型的Copy

正如你所提到的,不实施Copy的另一个原因是大类型。对于这种类型仅实施Clone可能是有用的,因为通常“Clone但不是Copy”表示克隆该值不是“便宜”。但是,即使某个类型不是Copy,仍然可以通过仅移动该值而导致大量内存复制操作(尽管如果幸运的话,编译器可能会优化它)。

如果类型的大小是“大”,执行Copy是否会对性能造成不利影响?

不是如果你从来没有在类型上执行副本!请记住,移动副本之间的唯一区别是移动会导致源无法使用(即,如果在移动后尝试使用某个值,则编译器会引发错误),而副本不会“T;这两个操作都是作为浅存储器副本来实现的。

+1

值得一提的是,即使你知道一个类型可以实现'Copy',你可能会选择不这样做以保留“移动”语义。 – BurntSushi5

+1

另一件需要注意的事情是非'Copy'是* safe *的默认值。如果你通过包装一个原始指针来实现你自己的'Box'版本,那么这样一个类型*就可以适用于任何隐式的'Copy'实现,这意味着程序员必须主动考虑'Copy的正确性'在每种类型上,并记住在需要时禁用它。在目前的设计中,如果程序员忘记考虑'Copy' ...什么也没有发生,没有任何事情可以打破。 –

相关问题