Rust'un sahiplik modeline genel bir C ++ sarmalayıcıyla ulaşmak mümkün mü?


15

Rust'un eşzamanlılık güvenliği hakkındaki bu makaleyi inceleyerek:

http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html

Bu fikirlerden kaçının C ++ 11'de (veya daha yenisinde) başarılabileceğini merak ediyordum. Özellikle, sahipliğini geçirilebilecek herhangi bir yönteme aktaran bir sahip sınıfı oluşturabilir miyim? Görünüşe göre C ++, imkansız olacağını değişkenleri geçmek için pek çok yolu var, ama belki bazı şablon kodu her yöntem geçişi yürütülür sağlamak için sınıf veya şablon üzerinde bazı kısıtlamalar koyabilirsiniz?


Bağlantıdan bazı alıntılar bu soruyu geliştirir
Martin Ba

2
@delnan (Güvenli) Rust, bir kerede bir şeye asla birden fazla değişebilir referansınızın bulunmamasını ve salt okunur referanslara sahip olduğunuz bir şeye asla değişebilir bir referansınızın bulunmamasını garanti eder. Ayrıca, iş parçacıkları arasında veri aktarımı konusunda bazı kısıtlamalar vardır. Bunlar, tek bir iş parçacıklı kodda bile, önemli hatalar oluşturmayı önler ve nesnelerin durumu hakkında muhakemeyi kolaylaştırır.
CodesInChaos

3
C ++ derleyicisinin doğrulayabileceği şekilde borçlanmayı ifade edebileceğinizi düşünmüyorsunuz, dolayısıyla ilişkili performans isabeti ile çalışma zamanı uygulamasına başvurmanız gerekir.
CodesInChaos

1
Kapsam sahiplikleri zaten C ++ 11'de akıllı işaretçiler tarafından uygulanmıyor mu?
Akshat Mahajan

1
@JerryJeremiah Rust çok çeşitli referans türlerine sahiptir. Temel olanlar, &herhangi bir tanıtımın kullanılmasını gerektirmez. Bir &mutsüre daha almaya devam ederseniz, aynı öğeye başka bir referansınız (değiştirilebilir veya değiştirilemez) varsa derleyemezsiniz. RefCell<T>Eğer denerseniz panik alırsınız hamle çek, zaman çalıştırmak için .borrow_mut()zaten aktif olduğu şeye .borrow()ya .borrow_mut(). Rust ayrıca Rc<T>(paylaşılan Weak<T>sahiplik işaretçisi) ve kardeşine sahiptir , ancak bunlar değişebilirlikle değil mülkiyetle ilgilidir. Değiştirilebilirlik için RefCell<T>içlerine yapıştırın.
8bittree

Yanıtlar:


8

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_ptrAkı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_ptrhareket 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 .


Sorun şu ki, C ++ temel dilde sahipliği izlemiyorsa, bu işlevi meta programlama yoluyla uygulamak mümkün müdür? Bu, (1) yalnızca aynı sınıftaki akıllı işaretçileri kullanan nesnelere ve (2) şablonlar aracılığıyla sahipliği izlemeye zorlayan, belleğe güvenli olacak yeni bir akıllı işaretçi sınıfı oluşturacağınız anlamına gelir
Elliot Gorokhovsky

2
@ElliotGorokhovsky Hayır, çünkü şablon referanslar gibi temel dil özelliklerini devre dışı bırakamaz. Akıllı bir işaretçi referans almayı zorlaştırabilir, ancak bu noktada dille savaşıyorsunuz - çoğu standart kütüphane işlevinin referanslara ihtiyacı var. Bir referansın ömrünü şablonlar aracılığıyla kontrol etmek de mümkün değildir, çünkü dil yeniden bir yaşam boyu kavramı sunmaz.
amon

Anlıyorum, teşekkürler
Elliot Gorokhovsky
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.