コピーとクローンの違いは何ですか?


回答:


114

Cloneは、任意の複製用に設計されています。Clone型の実装はT、新しいの作成に必要な複雑な操作を任意に実行できますT。これは通常の特性(プレリュードにあることを除く)であるため、通常の特性のように、メソッド呼び出しなどで使用する必要があります。

Copyトレイトは、安全を経由して複製することができる値を表しmemcpy:再割り当てし、常に機能することにより、値の引数を渡しているようなものmemcpyだが、そのためのためCopyの型、コンパイラはそれがそれらを検討する必要がないことを理解して動きます


5
CloneディープコピーとCopyシャドウコピーを理解できますか?
Djvu

11
Clone型が深いコピーまたは浅いコピーのいずれかを行う可能性を開きます:「任意に複雑」。
poolie 16

85

主な違いは、クローンが明示的であることです。暗黙の表記は、Copy型以外の移動を意味します。

// u8 implements Copy
let x: u8 = 123;
let y = x;
// x can still be used
println!("x={}, y={}", x, y);

// Vec<u8> implements Clone, but not Copy
let v: Vec<u8> = vec![1, 2, 3];
let w = v.clone();
//let w = v // This would *move* the value, rendering v unusable.

ちなみに、すべてのCopyタイプもである必要がありますClone。ただし、同じことをする必要はありません。独自のタイプの場合.clone()は、任意のメソッドを選択できますが、暗黙的なコピーは常に実装memcpyではなくをトリガーしclone(&self)ます。


1
涼しい!これは、クローントレイトが暗黙のコピーを提供するかどうかについて私が持っていた二次的な質問を明らかにします。その質問が判明し、これは私が思っていたよりも関連性が高かった。ありがとう!
user12341234 2015年

最初の例では、最後にコメント化した例のように、コピーではなくy移動したいとxしますw = v。それをどのように指定しますか?
ジョンベイカーズ

2
例のCopyように「安い」タイプのために実装されることを意図しているため、できませんu8。コピーよりも移動の方が効率的であると思われる非常に重い型を作成する場合は、 implにしないでくださいCopy。u8の場合、内部ではおそらく少なくともポインターのコピーが必要になるため、移動の効率を上げることはできないことに注意してください-すでにu8のコピーと同じくらい高価ですが、それがなぜかわからないのです。
mdup

これは、Copy特性の存在が変数の暗黙的な有効期間スコープに影響を与えることを意味しますか?もしそうなら、それは注目に値すると思います。
ブライアンカイン

6

他の回答ですでにカバーされているように:

  • Copy 暗黙的で安価であり、再実装できません(memcpy)。
  • Clone 明示的であり、コストがかかる可能性があり、任意に再実装できる場合があります。

Copyvs の説明で時々欠けているのCloneは、コンパイラが移動と自動コピーを使用する方法にも影響を与えるということです。例えば:

#[derive(Debug, Clone, Copy)]
pub struct PointCloneAndCopy {
    pub x: f64,
}

#[derive(Debug, Clone)]
pub struct PointCloneOnly {
    pub x: f64,
}

fn test_copy_and_clone() {
    let p1 = PointCloneAndCopy { x: 0. };
    let p2 = p1; // because type has `Copy`, it gets copied automatically.
    println!("{:?} {:?}", p1, p2);
}

fn test_clone_only() {
    let p1 = PointCloneOnly { x: 0. };
    let p2 = p1; // because type has no `Copy`, this is a move instead.
    println!("{:?} {:?}", p1, p2);
}

最初の例(PointCloneAndCopy)は暗黙的なコピーのためにここでは正常に機能しますが、2番目の例(PointCloneOnly)は移動後の使用でエラーになります。

error[E0382]: borrow of moved value: `p1`
  --> src/lib.rs:20:27
   |
18 |     let p1 = PointCloneOnly { x: 0. };
   |         -- move occurs because `p1` has type `PointCloneOnly`, which does not implement the `Copy` trait
19 |     let p2 = p1;
   |              -- value moved here
20 |     println!("{:?} {:?}", p1, p2);
   |                           ^^ value borrowed here after move

暗黙の移動を回避するために、明示的にを呼び出すことができますlet p2 = p1.clone();

これは、コピートレイトを実装する型の移動を強制する方法の問題を提起する可能性がありますか?。短い答え:できない、または意味がありません。


@Shepmaster Rustコンパイラの素敵な色分けが含まれているため、読みやすくなっていますが、検索に関連するすべての単語がテキストに含まれていることを確認しました。
bluenote10
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.