RAII nedir? Örnekler?


19

Her zaman RAII terimi kullanıldığında, insanlar aslında başlatma yerine yapısökümden bahsediyorlar. Bunun ne anlama gelebileceğine dair temel bir anlayışım olduğunu düşünüyorum ama tam olarak emin değilim. Ayrıca: C ++ tek RAII dili midir? Java veya C # /. NET ne olacak?

Yanıtlar:


25

Kaynak Edinimi Başlatma, nesnelerin kendilerine tam bir paket olarak bakmaları ve diğer kodların bir örneğe "Bu arada, yakında temizleneceksiniz - lütfen hemen toplayın" ifadesini beklememeleri gerektiği anlamına gelir. Bu genellikle yıkıcıda anlamlı bir şey olduğu anlamına gelir. Ayrıca, özel durumları yönetmek için tahmin edilmesi zor koşullar altında atılan istisnalar gibi, yürüten yıkıcılara güvenebileceğinizi bilerek, özellikle kaynakları yönetmek için bir sınıf yazmanız anlamına gelir.

Diyelim ki windows imlecini bir bekleme (kum saati, çalışmayan çörek, vb.) İmlecine değiştireceğiniz bir kod yazmak, eşyalarınızı yapın ve geri değiştirin. Ayrıca, "eşyalarını yap" ın bir istisna oluşturabileceğini de söyleyin. Bunu yapmanın RAII yolu, ctoru imleci beklemeye ayarlayan, bir "gerçek" yöntemi istediğiniz her şeyi yapan ve dtor imleci geri ayarlayan bir sınıf yapmak olacaktır. Kaynaklar (bu durumda imleç durumu) bir nesnenin kapsamına bağlıdır. Kaynağı aldığınızda bir nesneyi başlatırsınız. İstisnalar atılırsa, yok edilecek nesneye güvenebilirsiniz ve bu da kaynağı temizlemeye güvenebileceğiniz anlamına gelir.

RAII'yi iyi kullanmak, ihtiyacınız olmadığı anlamına gelir finally. Elbette, Java'da sahip olamayacağınız deterministik yıkıma dayanır. C # ve VB.NET ile bir tür deterministik yıkım alabilirsiniz using.


4
Sanırım bu elde ettiğiniz, ancak Java ve C # 'ın RAII'yi desteklememesinin nedeninin çöp toplayıcıdan kaynaklandığını eklemek isteyebilirsiniz. C ++ 'da, yerel bir nesne kapsam dışına çıkar çıkmaz yok edilir. Java / C # 'da bu doğru değildir.
Jason Baker

Jasons'un noktasında genişleyen Java ve C # 'ın zamanında imhayı garanti edememesinin nedeni referans döngüleri olasılığıdır, bu da yıkıcıları çalıştırmak için güvenli bir siparişin belirlenmesinin imkansız olduğu anlamına gelir. Referans döngüleri C ++ 'da da olabilir, ancak sonuçları farklıdır - programcı imha sırasını belirlemek ve açık silme işlemleri yapmaktan sorumlu hale gelir. Bu sorumluluk genellikle bazı üst düzey sınıf yıkıcılarında toplanır - örneğin, bir kap sınıfı, içerilen tüm öğelerin yok edilmesini sağlamaktan sorumludur. "Mülkiyet" anahtardır.
Steve314

1
@Jason "deterministik yıkım" ile kastettiğim budur - bir C ++ programcısı yıkıcının ne zaman çalışacağını bilir.
Kate Gregory

Bunun eski bir cevap olduğunu biliyorum, ama hala biraz kafam karıştı. Bu terimi yeni öğrendim ve bazı bilgiler satın almanın kurucuda gerçekleşmesi gerektiğini söylüyor. Bu benim için gerçekten mantıklı değil ve bu cevap onunla çelişiyor gibi görünüyor, ama açıklığa kavuşturabilir misin?
Per Johansson

1
@PerJohansson Evet, kratorda kazanıyorsun. Ve siz dtorda serbest bırakıyorsunuz. İkinci noktaya odaklanıyordum, ama birlikte gidiyorlar. Ctor bittikten sonra geçerli bir nesneniz olduğunu biliyorsunuz. Ve ne olursa olsun, kaynağın doğru zamanda serbest bırakılacağını biliyorsunuz.
Kate Gregory

4

RAII kısmen, bir nesnenin kendi temizliğinden ne zaman sorumlu olacağına karar vermekle ilgilidir - kural, yapıcısı başlatma işlemi tamamlandığında ve ne zaman tamamlandığında nesnenin sorumlu hale gelmesidir. Başlatma ve temizleme, yapıcı ve yıkıcı simetrisi, ikisinin birbiriyle yakın bağları olduğu anlamına gelir.

RAII'nin bir noktası, istisna güvenliği sağlamaktır - istisnalar atıldığında uygulamanın kendi kendine tutarlı kalması. İlk bakışta bu önemsizdir - bir istisna bir kapsamın çıkmasına neden olduğunda, o kapsamdaki yerel değişkenlerin yok edilmesi gerekir.

Ancak, istisna atımı bir kurucu içinde gerçekleşirse ne olur?

Nesne tam olarak inşa edilmedi, bu yüzden güvenli bir şekilde yok edilemez. Oluşturucu, istisna oluşturulmadan önce gerekli temizlemelerin yapılmasını sağlamak için gereken şekilde blokları denemelidir. İstisna, nesnenin inşa edildiği kapsamın dışında propogasyona uğradıktan sonra, herhangi bir yıkıcı çağrısı olmayacaktır, çünkü nesne ilk etapta inşa edilmemiştir.

Özellikle tahrip edilecek nesnenin içindeki üye verileri için yapıcıları düşünün. Bunlardan biri bir istisna atarsa, ana kurucu kodunuz hiç çalışmaz - ancak bu kurucunun örtük bir parçasını oluşturan bazı kodlar olacaktır. Başarıyla oluşturulmuş üyeler otomatik olarak imha edilecektir. İnşa edilmemiş üyeler (istisna atan üyeler dahil) değildir.

Yani temelde RAII, tamamen istisna edilen her şeyin, özellikle istisna atışlarının varlığında zamanında tahrip edilmesini ve herhangi bir nesnenin tamamen inşa edilmesini veya yapılmamasını (yarı- nasıl güvenli bir şekilde temizleneceğini bilemeyeceğiniz inşa edilmiş nesneler). Tahsis edilen kaynaklar da serbest bırakılır. Ve işlerin çoğu otomatiktir, bu yüzden programcı bu konuda fazla endişelenmek zorunda değildir.

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.