Soruya Giriş
Rust'ta iki ana dize türü vardır — &str (değiştirilemeyen dize dilimi, genellikle dize literal) ve String (dinamik, değiştirilebilir dize). Dilin erken geliştirme aşamalarında, bunlar arasındaki seçim, bellek yönetimini basitleştirmeye ve metin verileri işleme sırasında tür güvenliğini sağlamaya olanak tanıdı; bu, sıkı mülkiyet ve referans sistemi sayesinde gerçekleşti.
Sorun
Birçok geliştirici bu türler arasında etkileşimde bulunurken kafa karışıklığı yaşıyor. Örneğin, dize literal bir &'static str'dir, yani derleme sırasında ayrılan değiştirilemeyen bir dizeye işaret eden bir referanstır, oysa String dinamik olarak genişleyebilir ve çalışma zamanında elde edilen verileri içerebilir. Türler arasında nasıl dönüşüm yapılacağı, mülkiyetin nasıl doğru kullanılacağı ve gereksiz kopyalamalardan nasıl kaçınılacağı gibi sorular ortaya çıkmaktadır.
Çözüm
&str ve String arasındaki dönüşüm, temel mülkiyet kurallarını anladığınız sürece şeffaftır:
String'den bir dilim almak için referans (my_string.as_str()) veya basit ödünç alma (&my_string) kullanabilirsiniz.&str'yi String'e dönüştürmek için to_string() veya String::from() kullanabilirsiniz.Kod örneği:
fn main() { let s_literal: &str = "hello"; let s_string: String = String::from(s_literal); let s_slice: &str = &s_string; let new_string = s_slice.to_string(); println!("{} {}", s_string, new_string); }
Anahtar özellikler:
&str yığında yer kaplamaz, her zaman değiştirilemez.String dinamik olarak bellek ayırır, değiştirilebilir.Rust'ta dize literalini değiştirmek mümkün mü?
Hayır, dize literal (&'static str) her zaman değiştirilemezdir, herhangi bir karakteri değiştirme girişimi derleme aşamasında hata ile sonuçlanır.
Bir &str üzerinde .to_string() çağırmak, gereksiz kopyalamalar olmadan değiştirilebilir bir dize almak için yeterli mi?
Hayır, .to_string() her zaman yeni bellek ayırır ve içeriği kopyalar. Bu, bir dilim temelinde değiştirilebilir bir dizeye ihtiyacınız olduğunda kaçınılmazdır.
Bir String'den &str referansı almak, yaşam süresi sızıntısı riski taşır mı?
Evet, bu şekilde alınan referans (let s: &str = &my_string;) orijinal String'den daha uzun yaşamaz. Bir fonksiyondan yerel bir String'den &str döndürmeye çalışmak yaşam süresi hatası ile sonuçlanır.
String üzerinde &str referansı tutmak, görünümden düşer&str'yi String'e gereksiz yere dönüştürmek (gereksiz tahsisatlar)String::from("text")'in veri kopyası oluşturmayacağını beklemekFonksiyon, fonksiyon içinde geçici bir String'e referans veren &str döndürür:
fn faulty() -> &str { let s = String::from("Oops"); &s // yaşam süresi hatası! }
Artıları:
Eksileri:
Fonksiyon hemen bir String döndürür ve çağırana mülkiyeti devreder:
fn correct() -> String { String::from("Safe!") }
Artıları:
Eksileri: