Kopyala ve Klonla arasındaki fark nedir?


128

Bu sorun , bunun yalnızca bir uygulama ayrıntısı ( memcpyvs ???) olduğunu ima ediyor gibi görünüyor , ancak farklılıkların açık bir açıklamasını bulamıyorum.


Rust'un kaynak kodunun ilgili açıklaması var
duan

Yanıtlar:


115

Clonekeyfi çoğaltmalar için tasarlanmıştır: Bir Clonetür için bir uygulama, Tyeni bir T. Bu normal bir özelliktir (başlangıçta olmaktan başka) ve bu nedenle normal bir özellik gibi, yöntem çağrılarıyla vb. Kullanılmasını gerektirir.

CopyÖzellik güvenle yoluyla kopyalanabilir değerleri temsil memcpy: dönüşlerinde ve her zaman bir işleve by-değeri bir argüman vardır geçirerek gibi şeyler memcpys ve böylece için Copytürleri, derleyici bu o dikkate almak gerekmez anlar bir hareket .


5
CloneDerin kopya ve Copygölge kopya olarak anlayabilir miyim ?
Djvu

11
CloneYazının derin ya da yüzeysel bir kopya yapma olasılığını açar : "keyfi olarak karmaşık".
poolie

85

Temel fark, klonlamanın açık olmasıdır. Örtülü gösterim, Copytür olmayan için hareket anlamına gelir .

// 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.

Bu arada her Copytürün de olması gerekiyor Clone. Ancak aynı şeyi yapmak zorunda değiller! Kendi türleriniz için, .clone()seçtiğiniz keyfi bir yöntem olabilir, oysa örtük kopyalama her zaman uygulamayı memcpydeğil a'yı tetikleyecektir clone(&self).


1
Güzel! Bu, Klon özelliğinin örtük kopyalama sağlayıp sağlamadığına ilişkin ikincil bir soruyu temizliyor. Bu soru ortaya çıktı ve bu düşündüğümden daha alakalıydı. Teşekkürler!
user12341234

İlk örneğinizde, son yorum yaptığınız örnekte olduğu gibi bir kopyasını değil, ytaşınmasını istediğinizi varsayalım . Bunu nasıl belirtirsiniz? xw = v
johnbakers

2
Yapamazsınız ve yapamazsınız, çünkü örnekteki Copygibi "ucuz" tipler için uygulanmalıdır u8. Eğer bir hareket bir kopyasını daha etkilidir düşündüğümüz için oldukça ağır tip, yazarsanız, bunu yapmak değil impl Copy. U8 durumunda, bir hareketle daha verimli olamayacağınıza dikkat edin, çünkü kaputun altında muhtemelen en azından bir işaretçi kopyası gerektirecektir - ki bu zaten bir u8 kopyası kadar pahalıdır, öyleyse neden zahmet etmelisiniz.
mdup

Bu, Copyözelliğin varlığının değişkenlerin örtük yaşam süresi kapsamları üzerinde bir etkisi olduğu anlamına mı geliyor ? Öyleyse bunun dikkate değer olduğunu düşünüyorum.
Brian Cain

7

Zaten diğer yanıtların kapsadığı gibi:

  • Copy örtüktür, ucuzdur ve yeniden uygulanamaz (memcpy).
  • Clone açıktır, pahalı olabilir ve keyfi olarak yeniden uygulanabilir.

CopyVs tartışmasında bazen eksik Cloneolan şey, derleyicinin hamle ve otomatik kopyaları nasıl kullandığını da etkilemesidir. Örneğin:

#[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);
}

İlk örnek ( PointCloneAndCopy) örtük kopya nedeniyle burada iyi çalışıyor, ancak ikinci örnek ( PointCloneOnly) taşıma sonrası kullanımda hata veriyor:

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

Örtük hareketten kaçınmak için açıkça arayabiliriz let p2 = p1.clone();.

Bu , Kopyalama özelliğini uygulayan türde bir hareketin nasıl zorlanacağı sorusunu gündeme getirebilir. . Kısa cevap: Mantıklı değilsin / değil.


@Shepmaster Rust derleyicisinin güzel renk kodlamasını içerdiği için çok daha okunaklı bulsam da kaldırdım ve özellikle arama ile ilgili tüm kelimelerin metinde yer aldığından emin oldum.
bluenote10
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.