Copy
Clone に似ていますが、型がビット単位でコピー可能であることを示します。
derive 可能: ✅
// Copyright 2025 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Debug, Clone, Copy)] pub struct Copyable(u8, u16, u32, u64); fn main() { let copyable = Copyable(1, 2, 3, 4); let copy = copyable; // 暗黙的なコピー操作 dbg!(copyable); dbg!(copy); }
-
Cloneは明示的な、ユーザー定義のコピー操作を表します。Copyは暗黙的なビット単位コピーを表します。 -
一般に、プリミティブ値のように振る舞うべき「プレーンデータ」型にのみ実装すべきです。たとえば、線形代数ライブラリにおけるプリミティブな数値型などです。
-
Cloneと同じ注意点があります。値を複製すると不変条件が破れるなら、その型はCopyを実装すべきではありません。 -
CloneとCopyは必ず一緒に derive しましょう!Copyを実装するときにCloneを手動で実装してはいけません。- コピー操作では
cloneメソッドは呼び出されないため、独自のClone実装は暗黙的なコピー操作とは異なる振る舞いをする可能性があります。CloneとCopyを両方一緒に derive することで、cloneを呼び出した結果がコピーを行った場合と同じになることが保証されます。
- コピー操作では
-
DropまたはCopyでないフィールドを持つ型には実装できません。-
クラスに質問してみましょう: ヒープデータ(
Vec、BTreeMap、Rcなど)を持つ型は、なぜCopyにできないのでしょうか?これらの型に対してビット単位コピーを行うと、ヒープデータを持つ型がポインタの排他的所有権を失い、Rust とそのエコシステムが通常保っている不変条件を壊すことになります。
複数の
Vecがメモリ内の同じデータを指すことになります。データの追加や削除は、それぞれのVecの長さと容量の値しか更新しません。BTreeMapでも同様です。Rcをビット単位でコピーしても、ポインタ内の参照カウント値は更新されません。その結果、自分がそのポインタに対する唯一のRcだと思っているRc値のインスタンスが 2 つ存在しうることになります。そのうち 1 つが破棄されると、もう 1 つのRcがまだ生きているにもかかわらず、片方では参照カウントが 0 になり、内部の値がドロップされてしまいます。
-