C ++ parametrelerini bir işleve iletmenin üç yolu vardır: değere, lvalue referansına ve rvalue referansına göre. Bunlardan, değere göre geçmek, çağrılan işlevin kendi kopyasını alması anlamında sahiplik yaratır ve değer referansı ile geçmek, değerin tüketilebileceğini, yani artık arayan tarafından kullanılamayacağını gösterir. Lvalue referansıyla geçmek, nesnenin geçici olarak arayandan ödünç alınması anlamına gelir.
Ancak, bunlar “kural gereği” olma eğilimindedir ve derleyici tarafından her zaman kontrol edilemez. Ve kullanarak bir lvalue referansını yanlışlıkla bir rvalue referansına dönüştürebilirsiniz std::move()
. Somut olarak, üç sorun vardır:
Bir başvuru, başvurduğu nesneden daha uzun olabilir. Rust'un ömür boyu sistemi bunu engeller.
Herhangi bir zamanda aktif birden fazla değişebilir / sabit olmayan referans olabilir. Rust'un borç kontrol cihazı bunu önler.
Referansları devre dışı bırakamazsınız. Bir çağrı sitesinde, çağrılan işlevin imzasını bilmeden, bu işlevin nesnenize başvuru oluşturup oluşturmadığını göremezsiniz. Bu nedenle, ne sınıflarınızın herhangi bir özel yöntemini silerek ne de çağrı sitesini bazı “referans yok” stil rehberine uygunluk açısından denetleyerek referansları güvenilir bir şekilde engelleyemezsiniz.
Yaşam boyu sorun temel bellek güvenliği ile ilgilidir. Başvurulan nesnenin süresi dolduğunda bir referans kullanmak elbette yasa dışıdır. Ancak, bir nesneyi içinde bir referans sakladığınızda, özellikle o nesne geçerli kapsamı aştığında, kullanım ömrünü unutmak çok kolaydır. C ++ türü sistem, nesne ömrünü hiç modellemediğinden bu durumu açıklayamaz.
std::weak_ptr
Akıllı işaretçiyi düz bir referansa benzer kodlama sahipliği semantik, ama referans amacı ile yönetilmektedir gerektirir shared_ptr
, yani referans sayılır. Bu sıfır maliyetli bir soyutlama değildir.
C ++ bir const sistemine sahip olsa da, bu bir nesnenin değiştirilip değiştirilemeyeceğini izlemez, ancak bir nesnenin söz konusu referans yoluyla değiştirilip değiştirilemeyeceğini izler . Bu, “korkusuz eşzamanlılık” için yeterli garanti sağlamaz. Buna karşılık, Rust, tek referans olan aktif bir değişken referans varsa (“Bu nesneyi değiştirebilen tek kişi benim”) ve değiştirilemeyen referanslar varsa, nesneye yapılan tüm referansların değiştirilemez olduğunu garanti eder. (“Nesneden okuyabilirken, hiç kimse onu değiştiremez”).
C ++ 'da, bir muteksi olan akıllı bir işaretçi aracılığıyla bir nesneye erişimi korumaya cazip gelebilirsiniz. Ancak yukarıda tartışıldığı gibi bir kez referansımız olduğunda beklenen ömründen kurtulabilir. Bu nedenle, böyle bir akıllı işaretçi, yönetilen nesnesine tek erişim noktası olduğunu garanti edemez. Böyle bir şema aslında pratikte işe yarayabilir, çünkü çoğu programcı kendilerini sabote etmek istemez, ancak bir tür sistem bakış açısından bu hala tamamen sağlamdır.
Akıllı işaretçilerle ilgili genel sorun, temel dilin üstünde kütüphaneler olmasıdır. Temel dil özellikleri kümesi bu akıllı işaretçilerin, örneğin std::unique_ptr
hareket oluşturuculara ihtiyaç duymasını sağlar . Ancak, öz dil içindeki eksiklikleri gideremezler. Bir işlevi çağırırken örtük olarak referans oluşturma ve birlikte sallanan referanslara sahip olma, temel C ++ dilinin sağlam olduğu anlamına gelir. Değişken referansları tek bir referansla sınırlayamama, C ++ 'nın her türlü eşzamanlılık ile yarış koşullarına karşı güvenliği garanti edemeyeceği anlamına gelir.
Tabii ki pek çok açıdan C ++ ve Rust, özellikle statik olarak belirlenmiş nesne yaşamları kavramları açısından, izin verilmediklerinden daha benzerdir. Ancak doğru C ++ programlarını yazmak mümkün olsa da (programcıların hiçbirinin hata yapmaması şartıyla), Rust tartışılan özelliklerle ilgili doğruluğu garanti eder .