RustのCopy & Cloneトレイト：違いを見分けられますか？

[![表紙](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/c71620b1-f354-456b-a5c1-fc5e9f6a046c.png)](https://leapcell.io/?lc_t=q_rustcopyclone)

## 兄弟のような Copy と Clone

Rust において、`Copy` と `Clone` のトレイトは、型のコピーの挙動を制御するために使用されます。これらを使うことで、型の値をどのようにコピーするか、またどのような状況でコピーが可能かを定義できます。本記事では、この二つのトレイトの役割と使い方について詳しく説明し、コード例を交えてその使用方法を紹介します。

## `Copy` トレイト

`Copy` トレイトは、型がビット単位でコピーできることを示します。このトレイトを実装した型は、代入、関数への引数渡し、戻り値として返す際に自動的にコピーされます。

### `Copy` トレイトとは？

`Copy` トレイトはマーカー・トレイト（marker trait）であり、メソッドを一切持ちません。このトレイトは単に「この型はビット単位でコピー可能である」ことを示すためのものです。

```rust
#[derive(Copy)]
struct Point {
    x: i32,
    y: i32,
}
```

### `Copy` トレイトの実装方法

`Copy` トレイトを実装するには、型の定義に `#[derive(Copy)]` 属性を追加する必要があります。さらに、`Copy` を実装する型は `Clone` も実装しなければならないため、`#[derive(Clone)]` も併せて指定します。

```rust
#[derive(Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}
```

もし `Copy` トレイトを実装しようとして `Clone` を実装しなかった場合、コンパイルエラーが発生します。例えば：

```rust
#[derive(Copy)]
struct Point {
    x: i32,
    y: i32,
}

// error[E0277]: the trait bound `Point: std::clone::Clone` is not satisfied
```

エラーメッセージが示す通り、`Point` 型が `Clone` トレイトを実装していないため、`Copy` を実装することができません。

これは、`Copy` を実装するすべての型が `Clone` も実装する必要があるためです。Rust では `clone` メソッドを明示的に呼び出す際、ユーザーがビット単位のコピーを意図していると判断されます。そのため、`Copy` トレイトを実装する場合、必ず `Clone` も実装しなければなりません。

### `Copy` トレイトを実装できる型

すべての型が `Copy` を実装できるわけではありません。以下の条件を満たす型のみが `Copy` を実装できます。

- 型自体が「POD（Plain Old Data）」型であること（つまり、ポインタや参照を含まないこと）。
- その型のすべてのフィールドが `Copy` を実装していること。

例えば、以下の型は `Copy` を実装できません。なぜなら、参照フィールドを含んでいるためです。

```rust
struct Foo<'a> {
    x: &'a i32,
}

// error[E0204]: the trait `Copy` may not be implemented for this type
impl Copy for Foo<'_> {}
```

### `Copy` トレイトが必要な理由

`Copy` トレイトを実装することで、型の値を代入や引数渡し、戻り値として返す際に明示的に `clone` を呼び出す必要がなくなります。

また、`Copy` 型の値は常にビット単位でコピーされるため、コピー処理のオーバーヘッドが少なくなります。これはプログラムのパフォーマンス向上に役立ちます。

## `Clone` トレイト

`Copy` とは異なり、`Clone` トレイトは型の値を明示的にコピーすることを可能にします。このトレイトを実装した型は、`clone` メソッドを呼び出して新しいコピーを作成できます。

### `Clone` トレイトとは？

`Copy` とは異なり、`Clone` は通常のトレイトであり、`clone` というメソッドを持っています。このメソッドは、新しいコピーを作成するために使用されます。

```rust
#[derive(Clone)]
struct Point {
    x: i32,
    y: i32,
}
```

### `Clone` トレイトの実装方法

`Clone` トレイトを実装するには、`#[derive(Clone)]` を指定するか、`clone` メソッドを手動で実装する方法があります。

```rust
#[derive(Clone)]
struct Point {
    x: i32,
    y: i32,
}

// `clone` メソッドを手動実装する場合
impl Clone for Point {
    fn clone(&self) -> Self {
        Self { x: self.x, y: self.y }
    }
}
```

### `Clone` トレイトを実装できる型

ほとんどすべての型は `Clone` を実装できます。新しいコピーを作成する方法さえ定義できれば、`Clone` を実装できます。

### `Clone` トレイトが必要な理由

`Clone` トレイトを使うことで、明示的に型の値をコピーできます。これは、ポインタや参照を含む型など、ビット単位のコピーができない場合に特に有用です。

さらに、`Clone` トレイトを実装することで、コピーの際に特定の処理を追加できます。例えば、`clone` メソッド内でリソースの確保やカウンタの更新を行うことが可能です。

## `Copy` と `Clone` の違いと関係

`Copy` と `Clone` の両方が型のコピーに関するトレイトですが、それぞれの役割には違いがあります。

- `Copy` はマーカー・トレイトであり、型がビット単位でコピー可能であることを示します。このトレイトを実装すると、代入や関数の引数・戻り値として自動的にコピーされます。
- `Clone` は通常のトレイトであり、`clone` メソッドを提供します。このメソッドを呼び出すことで、明示的に新しいコピーを作成できます。

さらに、`Copy` を実装するすべての型は `Clone` も実装しなければなりません。これは、明示的に `clone` を呼び出す際に、Rust がビット単位でコピーすることを保証するためです。

## 実例

以下に、`Copy` と `Clone` を使用したコード例を示します。

```rust
#[derive(Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p1 = Point { x: 1, y: 2 };
    let p2 = p1; // 自動コピー
    let p3 = p1.clone(); // 明示的なコピー
}
```

この例では、`Point` 型を定義し、`Copy` と `Clone` を実装しました。`main` 関数内で `Point` の値を別の変数に代入すると、`Copy` により自動的にコピーされます。また、`clone` メソッドを呼び出すことで、明示的に新しいコピーを作成できます。

---

### [私たちはLeapcell、Rustプロジェクトのホスティングの最適解です。](https://leapcell.io/?lc_t=q_rustcopyclone)

[![Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/991bb52b-25b2-403c-a932-7e146d60c473.png)](https://leapcell.io/?lc_t=q_rustcopyclone)

[Leapcell](https://leapcell.io/?lc_t=q_rustcopyclone)は、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです：

**複数言語サポート**

- Node.js、Python、Go、Rustで開発できます。

**無制限のプロジェクトデプロイ**

- 使用量に応じて料金を支払い、リクエストがなければ料金は発生しません。

**比類のないコスト効率**

- 使用量に応じた支払い、アイドル時間は課金されません。
- 例: $25で6.94Mリクエスト、平均応答時間60ms。

**洗練された開発者体験**

- 直感的なUIで簡単に設定できます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能なインサイトのためのリアルタイムのメトリクスとログ。

**簡単なスケーラビリティと高パフォーマンス**

- 高い同時実行性を容易に処理するためのオートスケーリング。
- ゼロ運用オーバーヘッド — 構築に集中できます。

[ドキュメントで詳細を確認！](https://docs.leapcell.io/)

[![Try Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/b700f3cd-cf9c-4a27-8767-ba805456d4bf.png)](https://leapcell.io/?lc_t=q_rustcopyclone)

Xでフォローする：[@LeapcellHQ](https://x.com/LeapcellHQ)

---

[ブログでこの記事を読む](https://leapcell.io/blog/rust-copy-vs-clone)