Rust'ın Gizemli Kutusu: Box<T> Tipi ve Diğer Dillerle Karşılaştırmalı İnceleme

[en] Read in English

2023-07-11

Rust dilinin sunduğu birçok özellik arasında, “Box” tipi en önemli olanlarından biridir. Yığın (stack) üzerinde hafıza sınırlamalarına sahip nesnelerin dinamik olarak ayrılan yığın (heap) üzerinde saklanmasına izin verir. Bu makalede, Rust dilinin Box tipini detaylı olarak inceleyeceğiz ve özelliklerini C#, Go ve Java dilleriyle karşılaştıracağız.

Rust’ta Box Tipi

Rust dilinde, Box tipi, verinin yığın (heap) üzerinde ayrılan hafızada saklanması gerektiğinde kullanılır. Bu, veri boyutunun derleme zamanında bilinmediği durumlarda veya verinin boyutunun çok büyük olduğu durumlarda kullanılır. Box tipi, derleme sürecinde otomatik olarak düşen bir akıllı işaretçidir (smart pointer). Yani, Box kullanıldığında, Rust hafıza güvenliğini ve bellek sızıntısını önler.

Box kullanımına basit bir örnek aşağıdadır:

fn main() {
    let b = Box::new(5);
    println!("b = {}", *b);
}

Bu örnekte, 5 değerine sahip bir tam sayı kutulanır ve b değişkenine atanır. Box değeri, * operatörü ile dereference edilebilir.

Rust’ın Box<T> tipinin çeşitli kullanım örneklerine daha derinlemesine bakalım:

Büyük Veri Yapıları

Bir veri yapısının boyutu çok büyük olduğunda, Rust’ta Box<T> kullanmak genellikle en iyi seçenektir.

fn main() {
    let big_data = Box::new([0; 1_000_000]);
    println!("{}", big_data[0]);
}

Bu örnekte, Box<T> kullanılmazsa, yığının (stack) kapasitesini aşabiliriz. Rust buna izin vermez ve bir hata oluşturur. Ancak, Box<T> kullanarak, veriyi heap’te saklayabilir ve böylece bu sorunu çözebiliriz.

Recursive Tip Tanımları

Rust’ın Box<T> tipi, recursive veri yapıları oluştururken de sıklıkla kullanılır. En basit örneği, bir ağaç yapısıdır.

enum Tree {
    Empty,
    Node(i32, Box<Tree>, Box<Tree>),
}

fn main() {
    let left = Tree::Node(5, Box::new(Tree::Empty), Box::new(Tree::Empty));
    let tree = Tree::Node(10, Box::new(left), Box::new(Tree::Empty));
}

Bu örnekte, her düğüm Node(i32, Box<Tree>, Box<Tree>) şeklinde tanımlanır. Bu, her düğümün bir değeri ve iki çocuğu olduğunu belirtir. Çocuklar, Box<T> tipindeki başka bir ağaçtır. Burada, Box<T> kullanımının nedeni, Tree enum’unun boyutunun, Node değerlerinin potansiyel boyutu nedeniyle bilinmemesidir. Box<T> ile, boyutu bilinmeyen değerleri güvenli bir şekilde kullanabiliriz.

Trait Nesneleri

Rust’ın Box<T> tipi, bir trait nesnesi oluşturmak için de kullanılabilir. Trait nesneleri, birden çok tipin aynı traiti paylaştığı durumlarda kullanılır.

trait Animal {
    fn make_noise(&self);
}

struct Dog;
impl Animal for Dog {
    fn make_noise(&self) {
        println!("Woof!");
    }
}

struct Cat;
impl Animal for Cat {
    fn make_noise(&self) {
        println!("Meow!");
    }
}

fn main() {
    let animals: Vec<Box<dyn Animal>> = vec![
        Box::new(Dog),
        Box::new(Cat),
    ];
    
    for animal in animals {
        animal.make_noise();
    }
}

Bu örnekte, Animal adında bir trait tanımlıyoruz ve Dog ve Cat structları bu traiti uyguluyor. Daha sonra bir Animal vektörü oluşturup içerisine Dog ve Cat ekliyoruz. Bu, farklı türlerde nesneleri aynı koleksiyonda tutmamıza olanak sağlar. Box<dyn Trait> kullanımı, runtime’da farklı türlerin aynı traiti uygulayabilmesini sağlar.

C#‘ta Box Kavramı

C# dilinde, Box tipi doğrudan yoktur. Ancak, boxing ve unboxing kavramları vardır. Boxing işlemi, bir değer tipini (örneğin, bir tam sayı) referans tipine (örneğin, bir nesneye) dönüştürme sürecidir. Unboxing ise tam tersidir.

Örnek:

int i = 123;
object o = i;  // boxing
int j = (int)o;  // unboxing

C#‘ta, boxing ve unboxing işlemleri performans maliyeti taşır. Rust’ın aksine, hafıza güvenliğini ve bellek sızıntısını önlemek için belirli bir mekanizma sağlamaz.

Go’da Box Kavramı

Go dilinde, Rust’ın Box tipine karşılık gelen bir mekanizma yoktur. Ancak, Go’da bir nesnenin pointer’ını oluşturabilir ve bu şekilde dinamik hafıza tahsisi yapabilirsiniz.

i := new(int)
*i = 5
fmt.Println(*i)

Go dilinde garbage collector bulunur. Bu nedenle, kullanılmayan hafıza otomatik olarak geri kazanılır.

Java’da Box Kavramı

Java’da, ilkel tipleri nesne tiplerine dönüştürme işlemine “boxing” denir. Bu, önceden tanımlanmış sarmalayıcı sınıflar kullanılarak yapılır. Örneğin, int tipi Integer tipine dönüştürülebilir. Java’da, otomatik boxing ve unboxing mekanizması vardır.

Integer boxedInt = Integer.valueOf(5);
int unboxedInt = boxedInt.intValue();

Java dilinde garbage collector bulunur ve bu sayede kullanılmayan hafıza otomatik olarak geri kazanılır.

Sonuç

Rust dilinin Box tipi, dinamik hafıza tahsisi için güçlü bir araçtır. Aynı zamanda otomatik bellek yönetimi sağlar ve hafıza güvenliğini garantiler. C#, Go ve Java dillerinde, bu kavramlar farklı şekillerde ele alınmıştır. Genel olarak, Rust dilinin Box tipi, C#‘nın boxing/unboxing mekanizmasına ve Go’nun pointer kavramına kıyasla daha güvenli ve etkilidir. Java’da otomatik boxing/unboxing işlemleri ve garbage collector mekanizması Rust’ın Box tipiyle benzer avantajlar sunar, ancak Rust, derleme zamanında hafıza güvenliğini garantilerken Java runtime’da garbage collector’a dayanır.



Bu gibi daha fazla gönderi...

Rustda Güçlü ve Verimli Veri İşleme: Iteratorlarla Tanışın!

2024-04-15 | #rust

Rust dilinde iteratorler, koleksiyonlar üzerinde gezinmek ve üzerlerinde işlemler yapmak için kullanılan yapılar arasında yer alır. Iteratorlar, veri koleksiyonlarının elemanlarına erişmek ve bu elemanlar üzerinde işlemler yapabilmek için kullanılır. Rust’ın sahiplik ve ödünç verme kuralları ile entegre şekilde çalıştıkları için güvenli ve etkili bir kullanım sunarlar. Iterator Tanımlama ve Kullanma Iterator’ı kullanmanın temel yolu .iter(), .iter_mut(), ve .into_iter() metodlarıdır. Bu metodlar, koleksiyonun sahiplik durumuna göre değişir: .iter(): Koleksiyonun immutable referansları üzerinden iterasyon yapar.

Devamı 


Rust ta Crate ler: Modülerlik ve Yeniden Kullanımın Temeli

2024-04-03 | #crates #rust

Rust, modern ve güvenli bir programlama dili olarak, yazılım geliştirme dünyasında hızla popülerlik kazanıyor. Rust’ın en önemli özelliklerinden biri, modülerlik ve yeniden kullanılabilirlik üzerine kurulu olmasıdır. Bu da “crate” adı verilen bir kavramla sağlanır. Bu makalede, Rust’ta crate’lerin ne olduğunu, nasıl kullanıldığını ve neden önemli olduğunu detaylı bir şekilde ele alacağız. Crate Nedir? Basitçe söylemek gerekirse, bir crate, bir Rust projesinin temel yapı taşıdır. Bir veya birden fazla modülü içerebilen bir paket veya kütüphane olarak düşünülebilir.

Devamı 


Enum ve Pattern Matching: Rust'ta Güçlü Veri Yapıları

2023-08-25 | #rust #rust-enums #rust-patternmatching

Rust programlama dilinde enum ve pattern matching özellikleri, tip güvenliği ve kod okunabilirliği için oldukça önemli ve güçlüdür. enum (enumerasyonlar), farklı varyantları (variant) olan bir türü temsil eder. pattern matching ise, bu varyantları kolayca ve güvenli bir şekilde ele almanıza olanak tanır. Enum Nedir? enum keyword’ü ile bir enumerasyon oluşturabilirsiniz. Her bir “varyant” farklı bir olası değeri temsil eder. enum Renk { Kirmizi, Yesil, Mavi, } Bu örnekte Renk adlı bir enum tanımladık ve içerisine Kirmizi, Yesil, ve Mavi adlı varyantları ekledik.

Devamı 