2017-09-12 30 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' ...什麼也沒有發生,沒有任何事情可以打破。 –

相關問題