SORU
16 HAZİRAN 2014, PAZARTESİ


Hareket vs Pas Kopyala

Hadi bu yapı var

struct Triplet {
    one: int,
    two: int,
    three: int,
}

Eğer bir fonksiyon için bu sınavı geçersem, örtülü olarakkopyalanan. Şimdi bazen bazı değerler olmadığını okudumcopyableve bu nedenle varhareket ettirinyerine. struct Triplet bu sigara yapmak için, mümkün olur muydu merak ediyorumcopyablenedense? Bu olacak pas söyleyen bazı ekstra özellik uygulamak gibiolmayan copyableve bu nedenle vardırhareket ettirinyerine.

Bir örtülü olmayan şeyler kopyalamak için Clone özellik uygulamak için her yerde okudumcopyableama ben asla böyle bir şey olması da tam tersiörtülü olarakcopyableve bunu yapmaolmayan copyableo kadartaşıryerine.

O bile mantıklı geliyor mu?

CEVAP
16 HAZİRAN 2014, PAZARTESİ


ÖnsözBu cevap opt-in built-in traits - önce yazıldı;özellikle the Copy aspects - uygulanmıştır. Blok tırnak sadece eski düzeni için uygulanan bölüm (soru sorulduğu zaman uygulanan bir) belirtmek için kullandım.


Eski: Temel soruyu cevaplamak için, bir işaretleyici alan NoCopy value bir depolama ekleyebilirsiniz. E. g.

struct Triplet {
    one: int,
    two: int,
    three: int,
    _marker: NoCopy
}

Ayrıca bir yıkıcı (Drop trait uygulama üzerinden) alarak yapabilirsin, ama marker türleri kullanarak yıkıcı bir şey yapıyorsa tercih edilir.

Türleri artık sizin türü için açıkça bunu uygulamak sürece Copy uygulamak değil yeni tanımlarken varsayılan olarak, bu hareket,:

struct Triplet {
    one: i32,
    two: i32,
    three: i32
}
impl Copy for Triplet {} // add this for copy, leave it out for move

Bu uygulama sadece her tür yeni struct enum içerdiği kendisi Copy ise var olabilir. Derleyici hata iletisi yazdırır. Ayrıca sadece yazın varyokDrop bir uygulama var.


Bu soruya cevap vermek istemedin... "ne hareketler oldu ve anlaşıldı mı?":

Öncelikle iki farklı tarif edeceğim "kopya":

  • birbayt kopyalayınolan sadece sığ kopyalama bir nesneyi byte-by-byte, aşağıdaki işaretçiler, örneğin varsa (&uint, u64) 16 bayt üzerinde bir 64-bit bilgisayar ve sığ bir kopya olur alarak bu 16 bayt ve çoğaltma onların değeri başka bir 16-bayt yığın bellekolmadan& diğer ucunda uint dokunaklı. Yani, memcpy arama için eşdeğer.
  • birsemantik kopyalayıngüvenli bir şekilde ayrı olarak eski için kullanılabilir (biraz) yeni bağımsız bir örneğini oluşturmak için bir değeri çoğaltarak. E. g. bir anlam kopyası Rc<T> içerir sadece artan başvuru sayısı ve anlamsal bir kopyasını Vec<T> içerir oluşturma Yeni bir ayırma ve sonra da anlamsal kopyalama her saklı elementler eski yeni. Bu olabilir derin kopyalarını (örneğin Vec<T>) veya sığ (örneğin Rc<T> dokunmaz saklı T), Clone gevşek bir tanım olarak küçük miktarda iş için gerekli anlamsal kopya bir değer türü T içinden &T T.

Pas gibi Cher-değeri bir baytlık bir kopyası vardır:

let x: T = ...;
let y: T = x; // byte copy

fn foo(z: T) -> T {
    return z // byte copy
}

foo(y) // byte copy

Ya T hamle olup olmadığını bayt sayfa "örtülü copyable". (Açık olmak gerekirse, mutlaka tam zamanında byte-by-byte kopyasını değil mi: derleyici kodu davranışları korunur.) Eğer kopya optimize etmek için ücretsiz.

Ancak, bayt kopya ile temel bir sorun var: eğer yıkıcı, örn . eğer çok kötü olabilir Bellek yinelenen değerleri ile sona

{
    let v: Vec<u8> = vec![1, 2, 3];
    let w: Vec<u8> = v;
} // destructors run here

Eğer w sadece düz bayt kopyalama v sonra orada olacağını gösteren iki vektör de aynı ayırma, hem de yıkıcı olan ücretsiz... neden a double free olan bir sorun. NB. Bunun gayet iyi, eğer yaptığımız bir anlam kopyalama v w beri w olurdu kendi bağımsız Vec<u8> ve yıkıcı olmazdı ayaklar altına birbirimizi.

Birkaç olası düzeltmeler var:

  • Programcı kolu, (o kadar kötü değil yani C yıkıcılar var, hayır... sadece bellek sızıntısı ile yerine. sol C. gibi yapalım :P )
  • Semantik bir kopyasını w kendi ayırma, böylece dolaylı olarak, kopyalama ve varsayılan C gibi gerçekleştirin.
  • Nezdinde değer v artık kullanılabilir ve yıkıcı çalışma yok, böylece mülkiyet gibi bir aktarım kullanır.

Son Pas yapıyorhareket ettirinkaynak statik olarak nerede olduğunu sadece tarafından değer kullanılır derleyici artık geçersiz bellek daha fazla kullanımı önler bu yüzden geçersiz.

let v: Vec<u8> = vec![1, 2, 3];
let w: Vec<u8> = v;
println!("{}", v); // error: use of moved value

Türleri yıkıcılargerekirhareket ederken kullanılan değer (aka zaman kopyalanan bayt), beri var yönetimi/mülkiyet bazı kaynak (örneğin, bir bellek ayırma veya bir dosya tanıtıcı) ve onun çok olası bir bayt kopyalar doğru yinelenen bu sahiplik.

"...Örtülü bir kopyası nedir?"

u8 gibi ilkel bir tip düşünün: bir bayt kopyalama basit, sadece tek bayt kopyalama ve semantik bir kopyası gibi basit, tek bayt kopyalayın. Özellikle, bir bayt kopyalayınsemantik bir kopyasını... Pas bile anlamsal ve bayt aynı kopya olan yakalar built-in trait Copy vardır.

Dolayısıyla, Copy bu tür tarafından değeri kullanır güvende kaynağını kullanmaya devam etmek, bu yüzden de otomatik olarak semantik kopyalarıdır.

let v: u8 = 1;
let w: u8 = v;
println!("{}", v); // perfectly fine

Eski: NoCopy işaretleyici Copy (ilkel tek içeren toplamları ve & gibi) olabilir türleri Copy olduğunu varsayarak derleyici otomatik davranışı geçersiz kılar. Ancak bu opt-in built-in traits uygulandığında değişen olacaktır.

Yukarıda da belirtildiği gibi, opt-in built-in özellikleri uygulanır, derleyici artık otomatik davranış vardır. Ancak, bu kural geçmişte otomatik davranışlar için kullanılan yasal Copy uygulamak için olup olmadığını kontrol etmek için aynı kurallar.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • gadgetgal38

    gadgetgal38

    9 HAZİRAN 2009
  • John Lynn

    John Lynn

    8 Ocak 2010
  • Michael Lummio

    Michael Lumm

    25 Mayıs 2007