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 を実装すべきではありません。

  • CloneCopy は必ず一緒に derive しましょう! Copy を実装するときに Clone を手動で実装してはいけません。

    • コピー操作では clone メソッドは呼び出されないため、独自の Clone 実装は暗黙的なコピー操作とは異なる振る舞いをする可能性があります。CloneCopy を両方一緒に derive することで、clone を呼び出した結果がコピーを行った場合と同じになることが保証されます。
  • Drop または Copy でないフィールドを持つ型には実装できません。

    • クラスに質問してみましょう: ヒープデータ(VecBTreeMapRc など)を持つ型は、なぜ Copy にできないのでしょうか?

      これらの型に対してビット単位コピーを行うと、ヒープデータを持つ型がポインタの排他的所有権を失い、Rust とそのエコシステムが通常保っている不変条件を壊すことになります。

      複数の Vec がメモリ内の同じデータを指すことになります。データの追加や削除は、それぞれの Vec の長さと容量の値しか更新しません。BTreeMap でも同様です。

      Rc をビット単位でコピーしても、ポインタ内の参照カウント値は更新されません。その結果、自分がそのポインタに対する唯一の Rc だと思っている Rc 値のインスタンスが 2 つ存在しうることになります。そのうち 1 つが破棄されると、もう 1 つの Rc がまだ生きているにもかかわらず、片方では参照カウントが 0 になり、内部の値がドロップされてしまいます。