1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

表紙

兄弟のような Copy と Clone

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

Copy トレイト

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

Copy トレイトとは?

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

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

Copy トレイトの実装方法

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

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

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

#[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 を実装できません。なぜなら、参照フィールドを含んでいるためです。

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 というメソッドを持っています。このメソッドは、新しいコピーを作成するために使用されます。

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

Clone トレイトの実装方法

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

#[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 メソッド内でリソースの確保やカウンタの更新を行うことが可能です。

CopyClone の違いと関係

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

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

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

実例

以下に、CopyClone を使用したコード例を示します。

#[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 型を定義し、CopyClone を実装しました。main 関数内で Point の値を別の変数に代入すると、Copy により自動的にコピーされます。また、clone メソッドを呼び出すことで、明示的に新しいコピーを作成できます。


私たちはLeapcell、Rustプロジェクトのホスティングの最適解です。

Leapcell

Leapcellは、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです:

複数言語サポート

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

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

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

比類のないコスト効率

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

洗練された開発者体験

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

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

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

ドキュメントで詳細を確認!

Try Leapcell

Xでフォローする:@LeapcellHQ


ブログでこの記事を読む

1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?