Rust neden var String
ve str
? Arasındaki farklar nelerdir String
ve str
? Bir kullanır zaman String
yerine str
tersi ve yardımcısı? Bunlardan biri kullanımdan kaldırılıyor mu?
Rust neden var String
ve str
? Arasındaki farklar nelerdir String
ve str
? Bir kullanır zaman String
yerine str
tersi ve yardımcısı? Bunlardan biri kullanımdan kaldırılıyor mu?
Yanıtlar:
String
dinamik yığın dize türüdür, örneğin Vec
: dize verilerinize sahip olmanız veya değiştirmeniz gerektiğinde kullanın.
str
, bellekte bir yerde dinamik uzunluktaki değişmez 1 UTF-8 baytlık bir dizidir. Boyut bilinmediği için, sadece işaretçi ile başa çıkabilir. Bu, str
en yaygın olarak 2'nin şu şekilde göründüğü anlamına gelir &str
: normalde "dize dilimi" veya yalnızca "dilim" olarak adlandırılan bazı UTF-8 verilerine başvuru. Dilim yalnızca bazı verilerin görünümüdür ve bu veriler herhangi bir yerde olabilir, ör.
"foo"
a &'static str
. Veriler yürütülebilir dosyaya sabit kodlanır ve program çalıştırıldığında belleğe yüklenir.String
: String
dereferences bir karşı &str
bakış arasında String
'in verilerine.Yığında : örn., Yığınla ayrılmış bir bayt dizisi oluşturur ve ardından bu verilerin&str
bir görünümünü aşağıdaki gibi alır :
use std::str;
let x: &[u8] = &[b'a', b'b', b'c'];
let stack_str: &str = str::from_utf8(x).unwrap();
Özet olarak, String
sahip olunan dize verilerine ihtiyacınız varsa kullanın (dizeleri diğer iş parçacıklarına geçirmek veya çalışma zamanında oluşturmak gibi) ve &str
yalnızca bir dize görünümüne ihtiyacınız varsa kullanın .
Bu, bir vektör Vec<T>
ile bir dilim arasındaki ilişkiye özdeştir ve genel tipler için &[T]
by-value T
ve by-reference arasındaki ilişkiye benzer &T
.
1 A str
sabit uzunluktadır; sonuna kadar bayt yazamaz veya sondaki geçersiz bayt bırakamazsınız. UTF-8 değişken genişlikli bir kodlama olduğundan, bu durum tüm str
durumlarda etkili bir şekilde değişmez olmaya zorlar . Genel olarak, mutasyon öncekinden daha fazla veya daha az bayt yazmayı gerektirir (örneğin bir a
(1 bayt) yerine ä
(2+ bayt) koymak için daha fazla yer açmak gerekir str
). Bir yerinde değişiklik yapabilen &str
, çoğunlukla yalnızca ASCII karakterlerini işleyen belirli yöntemler vardır make_ascii_uppercase
.
2 Dinamik olarak boyutlandırılmış türler , Rc<str>
Rust 1.2'den bu yana UTF-8 bayt olarak sayılan bir referans dizisi gibi şeylere izin verir . Rust 1.21 bu tiplerin kolayca oluşturulmasını sağlar.
[u8; N]
,.
Rc<str>
ve Arc<str>
artık standart kütüphane aracılığıyla kullanılabilir.
Bir C ++ arka plan var ve çok String
ve &str
C ++ açısından düşünmek için yararlı buldum :
String
a std::string
; hafızanın sahibidir ve hafızayı yönetmenin kirli işini yapar.&str
, char*
(ama biraz daha sofistike) gibidir; bizi içeriğinin bir göstergesini alabileceğiniz şekilde bir yığının başlangıcına yönlendirir std::string
.İkisi de yok olacak mı? Ben öyle düşünmüyorum. İki amaca hizmet ederler:
String
tamponu tutar ve kullanımı çok pratiktir. &str
hafiftir ve dizelere "bakmak" için kullanılmalıdır. Yeni bellek ayırmaya gerek kalmadan parçaları arayabilir, bölebilir, ayrıştırabilir ve hatta değiştirebilirsiniz.
&str
bir String
dize değişmezine işaret edebileceği için a'nın içine bakabilir . Aşağıdaki kodun değişmez dizeyi String
yönetilen belleğe kopyalaması gerekir :
let a: String = "hello rust".into();
Aşağıdaki kod, hazır bilginin kendisini kopya olmadan kullanmanızı sağlar (salt okunur)
let a: &str = "hello rust";
str
, yalnızca &str
bir dize dilimi, UTF-8 bayt dizisine başvuru olarak kullanılır.
String
eskiden ne ~str
bir growable, sahip olunan UTF-8 bayt dizisi.
~str
şimdiBox<str>
~str
yetiştirilebilir Box<str>
olmasa da yetiştirilebilirdi. (Bu ~str
ve ~[T]
diğer tüm ~
nesnelerin aksine büyülü bir şekilde büyüyebilirdi, tam olarak neden String
ve Vec<T>
tanıtıldı, böylece kurallar basit ve tutarlıydı.)
Aslında tamamen farklılar. Öncelikle, a str
bir tür düzey şeyden başka bir şey değildir; dinamik olarak boyutlandırılmış bir tür (DST) olduğu için yalnızca tür düzeyinde düşünülebilir. Alınan boyut str
derleme zamanında bilinemez ve çalışma zamanı bilgilerine bağlıdır - derleyicinin derleme zamanında her değişkenin boyutunun ne olduğunu bilmesi gerekir. A str
kavramsal olarak sadece u8
geçerli bir UTF-8 oluşturduğunu garanti eden bir bayt dizisidir. Sıra ne kadar büyük? Hiç kimse çalışma zamanına kadar bilmiyor, bu nedenle bir değişkende saklanamıyor.
İlginç olan bir olmasıdır &str
a veya başka bir işaretçi str
beğendiniz Box<str>
yapar zamanında mevcuttur. Bu sözde "şişman işaretçi" dir; ekstra bilgi içeren bir işaretçi (bu durumda işaret ettiği şeyin boyutu), bu yüzden iki kat daha büyük. Aslında a &str
, a'ya oldukça yakındır String
(ancak a'ya değil &String
). A &str
iki kelimedir; a'nın ilk baytına bir işaretçi str
ve kaç bayt uzunluğunu açıklayan başka bir sayı str
.
Söylenenlerin aksine, str
a'nın değişmez olması gerekmez. Eğer &mut str
özel bir işaretçi olarak alabilirsiniz str
, onu değiştirebilir ve onu değiştiren tüm güvenli fonksiyonlar UTF-8 kısıtlamasının desteklendiğini garanti eder, çünkü bu ihlal edilirse kütüphane bu kısıtlamanın doğru ve kontrol etmez.
Öyleyse a String
nedir? Bu üç kelime; iki ile aynıdır, &str
ancak str
yığın üzerinde arabellek kapasitesi olan , her zaman yığın üzerinde olan (a str
mutlaka yığın üzerinde değildir) üçüncü bir sözcük ekler ve doldurmadan önce yeniden ayırması gerekir. String
temelde sahibi bir str
dedikleri gibi; onu kontrol eder ve yeniden boyutlandırabilir ve uygun gördüğünde yeniden tahsis edebilir. Yani bir String
şekilde daha yakın bir söylenen &str
bir daha str
.
Başka bir şey bir Box<str>
; Bu aynı zamanda a str
ve çalışma zamanı temsiliyle aynıdır, &str
ancak bunun str
aksine de sahip &str
değildir , ancak yeniden boyutlandırılamaz çünkü kapasitesini bilmez, bu nedenle temel Box<str>
olarak bir String
yeniden boyutlandırılamayan sabit uzunluk olarak görülebilir ( her zaman String
yeniden boyutlandırmak istiyorsanız bir dönüştürün ).
UTF-8 kısıtlaması arasında [T]
ve Vec<T>
dışında çok benzer bir ilişki vardır ve boyutu dinamik olmayan herhangi bir türü tutabilir.
Kullanımı str
türü düzey ile jenerik soyutlamalar oluşturmak için çoğunlukla üzerinde &str
; özellikleri rahatça yazabilmek için tür düzeyinde bulunur. Teoride str
, tipik bir şeyin var olmasına gerek yoktu ve sadece &str
bu, şimdi genel olabilecek çok fazla kodun yazılması gerektiği anlamına geliyordu.
&str
String
kopyalamak zorunda kalmadan birden çok farklı alt dizeye sahip olabilmek için çok kullanışlıdır ; gibi bir sözü String
sahibistr
yönettiği öbek üzerinde ve yalnızca bir alt dize oluşturmak eğer String
yeni ile String
o Rust her şeyi okunur bellek güvenliği ile başa çıkmak için tek sahibi olabilir çünkü kopyalanan etmesi gerekir. Örneğin, bir dizeyi dilimleyebilirsiniz:
let string: String = "a string".to_string();
let substring1: &str = &string[1..3];
let substring2: &str = &string[2..4];
str
Aynı dizginin iki farklı alt dizesi var. yığın üzerinde string
gerçek tam str
tampon sahip olan ve &str
alt dizeleri yığın üzerinde bu tampon sadece yağ işaretçileridir.
std::String
basitçe bir vektörüdür u8
. Tanımını kaynak kodunda bulabilirsiniz . Öbek tahsis edilmiş ve yetiştirilebilir.
#[derive(PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct String {
vec: Vec<u8>,
}
str
dize dilimi olarak da adlandırılan ilkel bir türdür . Dize diliminin boyutu sabittir. Gibi bir hazır bilgi dizesi let test = "hello world"
vardır &'static str
türü. test
statik olarak tahsis edilen dizeye bir referanstır.
&str
örneğin değiştirilemez
let mut word = "hello world";
word[0] = 's';
word.push('\n');
str
değiştirilebilir dilim var &mut str
, örneğin:
pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str)
let mut s = "Per Martin-Löf".to_string();
{
let (first, last) = s.split_at_mut(3);
first.make_ascii_uppercase();
assert_eq!("PER", first);
assert_eq!(" Martin-Löf", last);
}
assert_eq!("PER Martin-Löf", s);
Ancak UTF-8'deki küçük bir değişiklik bayt uzunluğunu değiştirebilir ve bir dilim başvurusunu yeniden tahsis edemez.
Kolay bir deyişle, String
veri tipi yığın üzerinde depolanır (tıpkı gibi Vec
) ve bu konuma erişiminiz vardır.
&str
bir dilim türüdür. Bu String
, öbek içinde zaten mevcut olan bir yere atıfta bulunduğu anlamına gelir .
&str
çalışma zamanında herhangi bir ayırma yapmaz. Yani, hafıza nedenlerden dolayı kullanabileceğiniz &str
üzerinde String
. Ancak, kullanırken &str
açık yaşamlarla uğraşmanız gerekebileceğini unutmayın .
str
olduğunu view
zaten mevcut String
yığın.
C # ve Java kullanıcıları için:
String
===StringBuilder
&str
=== (değişmez) dizesi&str
Bir dize görünümü olarak düşünmek istiyorum, Java / C # 'de değiştirilemeyen bir staj dizisi gibi, sadece yeni bir tane oluşturun.
İşte hızlı ve kolay bir açıklama.
String
- Büyüyen, sahip olunan öbek tahsisli veri yapısı. A zorlanabilir &str
.
str
- (şimdi, Rust geliştikçe) öbekte veya ikili dosyada yaşayan mutable, sabit uzunlukta dizedir. Yalnızca, str
bir dize dilimi görünümü aracılığıyla ödünç alınmış bir tür olarak etkileşimde bulunabilirsiniz &str
.
Kullanımla ilgili hususlar:
String
Bir dizeye sahip olmak veya onu değiştirmek isteyip istemediğinizi (dizeyi başka bir diziye geçirmek vb.) Tercih edin.
&str
Bir dizenin salt okunur bir görünümüne sahip olmayı tercih edin.
&str
iki bileşenden oluşur: Bazı bayta bir işaretçi ve bir uzunluğa."