ProgramlamaRust Geliştirici

Rust'ta Copy ve Clone nasıl uygulanır ve çalışır? Hangi durumlarda Copy yeterli olur, ne zaman Clone gereklidir, kendi türleriniz için her ikisini nasıl doğru bir şekilde uygulayabilirsiniz ve bu, bir değerin sahipliği için ne anlama gelir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Sorunun tarihçesine bakalım:

Rust'ta bellek yönetimi ve sahiplik kavramı, nesnelerin hareket ettirilmesi ve kopyalanmasıyla ilgili net bir tanım gerektirir. Dilin başlangıcında, basit bayt kopyalama (ayrıcalıklı tahsisatlar ve mantık olmadan) ile derin kopyalama (örneğin, bir string veya vektör kopyası) arasında ayrıma gitmek önemlidir. Bunun için iki trait - Copy ve Clone - tanıtılmıştır.

Sorun, tüm veri türlerinin aynı derecede ucuz kopyalanmamasıdır. Bazı yapıların kopyalanması yalnızca bitlerin kopyalanmasıdır (örneğin, tamsayılar veya Copy türlerinden oluşan demetler), diğerleri için (örneğin, String, Vec) ek bellek tahsilatı gerektiren iş cinsinden çalışmalar ortaya çıkmaktadır. Copy ve Clone'un ayrılması, Rust'un geçersiz bir kopyalama yapmaya çalıştığınızda derleme hatası vermesini sağlar.

Çözüm:

  • Copy olarak işaretlenen türler, iletme, atama ve fonksiyonlara geçişte otomatik olarak kopyalanır. Bu türlerin nesneleri kopyalandıktan sonra geçerli kalır.
  • Karmaşık nesneler için Clone uygulanır ve bu, genellikle kaynakları tahsis eden .clone() yöntemi çağrısını gerektirir.

Kod örneği:

#[derive(Debug, Copy, Clone)] struct Point { x: i32, y: i32, } fn main() { let p1 = Point { x: 1, y: 2 }; let p2 = p1; // p1 geçersiz hale gelmez println!("{:?} {:?}", p1, p2); }

Anahtar özellikler:

  • Copy - otomatik bit kopyası, manuel çağrı gerektirmez ve sahipliği etkilemez.
  • Clone - belirgin bir derin kopya, heap verileri olan yapılar için uygundur.
  • Her iki trait de manuel olarak uygulanabilir, ancak Copy için katı sınırlamalar (tüm alanların Copy olması gerekir) vardır.

Kandırmaca Sorular.

Heap tahsili verileri olan türler Copy olarak türetilebilir mi?

Hayır, heap verileri içeren türler (örneğin, String, Vec) otomatik olarak Copy gerçekleştiremez, çünkü bu bellek iki katına çıkar.

Eğer bir tür Copy uygularsa, aynı zamanda farklı bir mantıkla Clone'u manuel olarak uygulayabilir miyiz?

Evet, Clone manuel olarak uygulanabilir ve mantık farklı olabilir, ancak Copy ve Clone arasında tutarlılık önerilmektedir: Copy, tahsis edilmeden Clone'u çağırır.

#[derive(Copy)] struct X; impl Clone for X { fn clone(&self) -> X { *self } }

Eğer bir yapı sadece Copy alanları içeriyorsa ama #[derive(Copy)] ile işaretlenmemişse, Copy olur mu?

Hayır, tür, bileşiminden otomatik olarak Copy olmaz - türünüz için Copy ile açıkça türetmek gereklidir.

Tipik hatalar ve anti paterni

  • Heap tahsili alanları olan türler için Copy uygulamak.
  • Move'dan sonra bir non-Copy türün örneğini kullanmaya çalışmak.
  • Copy'yi uygulayıp Clone'u uygulamayı unutmak, API kullanıcılarının beklentilerini bozar.

Gerçek Hayat Örneği

Olumsuz Durum

Heap verileri olan bir tür yanlışlıkla Copy olarak işaretlenirse, sonlandırma sırasında iki katına çıkar.

Artılar:

  • Derleyici bunu engellemeyecektir ancak unsafe kodu durumunda hata olasılığı vardır.

Eksiler:

  • Uygulamanın çökmesi.

Olumlu Durum

Hafif yapılar için Copy kullanmak (koordinatlar, renkler), karmaşık yapılar için Clone kullanmak (stringler, vektörler). Kod güvenli ve tahmin edilebilirdir.

Artılar:

  • Derleme aşamasında daha fazla güvenlik ve Şeffaf hatalar.

Eksiler:

  • Alanları net bir şekilde ayırt etmek ve Copy ile Clone arasındaki farkı anlamak gerekir.