Modül dersleri (2/2)
Akıllı İşaretçiler: Kutu ve Rc
Akıllı işaretçi, işaretçi gibi davranan ancak meta verilere ve ekstra yeteneklere (referans sayma veya otomatik bellek yönetimi gibi) sahip bir veri yapısıdır.
Rust'ta sıradan referanslar (& gibi) yalnızca verileri ödünç alır. Akıllı işaretçiler ise çoğunlukla işaret ettikleri verilerin sahibidir. Yaygın örnekler arasında String ve Vec<T> yer alır, ancak standart kitaplık başka özelleştirilmiş örnekler de sağlar.
Yığın Tahsisi için Kutu<T>
En basit akıllı işaretçi Box<T> olup verileri yığın yerine yığın üzerinde depolar. Yığın üzerinde yalnızca yığına ayrılmış verilere yönelik işaretçi kalır.
Esas olarak aşağıdaki durumlarda kullanılır:
- Derleme zamanında boyutu bilinemeyen bir türünüz olduğunda (özyinelemeli tür gibi) ve bu türdeki bir değeri tam boyut gerektiren bir bağlamda kullanmak istediğinizde.
- Büyük miktarda verinin sahipliğini kopyalamadan aktarmak istediğinizde.
Temel örnek:
fn main() {
let b = Box::new(5); // allocates the value 5 on the heap
println!("b = {}", *b); // dereferences with * to read the value
}Özyinelemeli Türler ve Eksileri Listeleri
Özyinelemeli tür, tanımının bir parçası olarak kendisinin değerini içerebilen bir türdür. Rust'ın derleme zamanında bir türün tam boyutunu bilmesi gerekir. Özyinelemeli bir türün derinliği sonsuz olabileceğinden, bir Kutu (bir işaretçi olduğundan sabit bir boyuta sahiptir) kullanmadığınız sürece derleyici bir hata üretir:
enum List {
Cons(i32, Box<List>),
Nil,
}Rc<T>: Referans Sayma
Tek bir değerin birden fazla sahibi olabileceği durumlar vardır. Rc<T> (Referans Sayımı) akıllı işaretçisi, değerin hala kullanımda olup olmadığını belirlemek için bir değere yapılan referansların sayısını takip eder. Sayım sıfıra düşerse kaynak güvenli bir şekilde serbest bırakılır.
[!NOT]
Rc<T>yalnızca tek iş parçacıklı senaryolar için uygundur. Çok iş parçacıklı (eşzamanlı) senaryolar içinArc<T>(Atomik Referans Sayımı) kullanmanız gerekir.
use std::rc::Rc;
fn main() {
let a = Rc::new(5);
let b = Rc::clone(&a); // increments the reference count to 2
println!("References: {}", Rc::strong_count(&a));
}Kendin dene
Alıştırma 1: Kutuyla Yığın Tahsisi
Box::new kullanarak heap'e 42 değerinde bir tamsayı değeri tahsis edin ve bunu val adlı bir değişkene atayın. Daha sonra, Kutuda saklanan değeri * operatörüyle açıkça referansını kaldırarak yazdırın.
İpucu göster
Değeri yığında saklamak için `let val = Box::new(42);` kullanın ve `println!` içindeki `*val` ile referansı kaldırın.
3 denemeden sonra çözüm mevcut
Alıştırma 2: Özyinelemeli Veri Yapısı (Eksileri Listesi)
İki değişken içeren List adlı özyinelemeli bir numaralandırma tanımlayın: Bir tuple'ı saran Cons (i32, Box<List>) ve listenin sonunu temsil eden Nil. Ana işlevde, 1 öğesini ve ardından Nil'i içeren bağlantılı bir liste oluşturun.
İpucu göster
Numaralandırma, 'enum List { Cons(i32, Box<List>), Nil }' olarak bildirildi. Listeyi `List::Cons(1, Box::new(List::Nil))` ile oluşturun.
3 denemeden sonra çözüm mevcut
Alıştırma 3: Sahipliği Rc ile Paylaşmak
a değişkeninde 100 değerini içeren paylaşılan bir tamsayı oluşturmak için std::rc::Rc kullanın. Referansı Rc::clone kullanarak b değişkenine kopyalayın. Son olarak Rc::strong_count fonksiyonunu kullanarak aktif referansların sayısını yazdırın.
İpucu göster
Değeri `Rc::new(100)` ile oluşturun. 'Rc::clone(&a)' ile klonlayın ve 'Rc::strong_count(&a)' ile sahip sayısını görüntüleyin.
3 denemeden sonra çözüm mevcut