Rust’ta String ve &str Arasındaki Kritik Farklar

  • Konbuyu başlatan Konbuyu başlatan irfo
  • Başlangıç tarihi Başlangıç tarihi

irfo

Moderatör
Katılım
7 Ocak 2026
Mesajlar
290
Tepkime puanı
2
Puanları
18
Rust öğrenmeye başladığınızda karşınıza çıkan en kafa karıştırıcı konulardan biri, metinleri temsil etmek için neden iki farklı yapı (String ve &str) olduğudur. Bu ayrım, Rust’ın bellek yönetimi (sahiplik ve ödünç alma) felsefesinin doğrudan bir sonucudur.
Bu iki yapı arasındaki farkı anlamak, sadece kodun derlenmesini sağlamakla kalmaz, aynı zamanda programınızın performansını da doğrudan etkiler.

1. String: Sahipli, Dinamik ve Büyütülebilir​

String tipi, Rust'ta "sahibi olduğunuz" (owned) metin verisidir. Veri, belleğin Heap (Öbek) kısmında saklanır.
  • Dinamiktir: Çalışma zamanında içeriği değiştirilebilir veya boyutu artırılabilir.
  • Sahiplik: String kapsam dışına çıktığında, tuttuğu bellek alanı otomatik olarak temizlenir.
  • Kullanım: Kullanıcıdan girdi alırken veya bir metni manipüle etmeniz (ekleme, çıkarma) gerektiğinde tercih edilir.
Kod:
 let mut s = String::from("Merhaba"); s.push_str(" Dünya"); // Metin değiştirilebilir println!("{}", s);

2. &str: Ödünç Alınmış, Sabit ve Bir "Slice"​

&str (string slice olarak okunur), bir metin verisinin belirli bir bölümüne veya tamamına verilen referanstır. Verinin sahibi değildir, sadece ona "bakar".
  • Sabittir: İçeriği değiştirilemez (immutable).
  • Bellek Konumu: Genellikle belleğin Stack (Yığın) kısmında veya ikili dosyanın (binary) veri bölümünde (string literals) bulunur.
  • Hafiftir: Sadece verinin başladığı adresi ve uzunluğunu tutan bir göstergedir.
Kod:
 let mesaj: &str = "Selam"; // Bu bir 'string literal'dır ve tipi &str'dir. // mesaj.push_str("!"); // HATA: &str değiştirilemez.

3. Bellek Yapısı: Stack vs Heap​

Aralarındaki en büyük fark bellekte nasıl temsil edildikleridir. String, Heap'teki veriyi yöneten bir yapı iken; &str, o veriye erişim sağlayan bir penceredir.
ÖzellikString&str
Bellek KonumuHeap (Öbek)Stack/Binary (İşaret ettiği yer Heap olabilir)
SahiplikVar (Sahibidir)Yok (Ödünç almıştır)
Boyut DeğişimiEvet (Büyüyebilir)Hayır (Sabittir)
Veri YapısıPointer + Uzunluk + KapasitePointer + Uzunluk

4. Dönüşümler (Conversion)​

İki tip arasında geçiş yapmak oldukça basittir ancak maliyetlerini bilmek gerekir:

  • &str -> String: to_string() veya String::from() kullanılır. Bu işlem Heap'te yeni bir alan ayırdığı için (allocation) bir maliyeti vardır.
  • String -> &str: & operatörü veya .as_str() kullanılır. Bu işlem çok hızlıdır çünkü yeni bir veri oluşturmaz, sadece bir referans verir.
Kod:
let s_dilimi: &str = "Rust";let s_string: String = s_dilimi.to_string(); // &str'den String'e

let geri_dilim: &str = &s_string; // String'den &str'ye (Dereffing)


5. Fonksiyon Parametrelerinde Hangisini Kullanmalı?​

Rust topluluğunun altın kuralı şudur: Eğer fonksiyonunuz metni değiştirmeyecekse, parametre olarak &str kullanın.

Neden? Çünkü &str parametresi alan bir fonksiyona hem &str tipindeki verileri hem de String referanslarını gönderebilirsiniz (Deref Coercion sayesinde). Bu, fonksiyonunuzu daha esnek kılar.

Kod:
fn selamla(isim: &str) {println!("Merhaba, {}!", isim);}

fn main() {let s = String::from("Ali");selamla("Veli"); // &str ile çalışırselamla(&s);     // String referansı ile de çalışır!}


Özet​

  • String bir kutu gibidir; içindeki metni siz yönetirsiniz, değiştirebilirsiniz ve çöpe atabilirsiniz.
  • &str ise bir cam gibidir; kutunun içindeki metni görmenizi sağlar ama ona dokunamaz veya kutunun boyutunu değiştiremezsiniz.
Programınızda sabit metinlerle çalışıyorsanız &str, dinamik ve değişen metinlerle uğraşıyorsanız String kullanın.
 
Geri
Üst