1018 Stimmen

Was sind die Unterschiede zwischen Rusts `String` und `str`?

Warum hat Rust sowohl String als auch str? Was sind die Unterschiede zwischen ihnen und wann sollte man eine gegenüber der anderen verwenden? Wird eine von ihnen veraltet?

19voto

Aperion Punkte 283

std::String ist einfach ein Vektor von u8. Du kannst die Definition in Quellcode finden. Es ist heap-allociert und erweiterbar.

#[derive(PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct String {
    vec: Vec,
}

str ist ein primitiver Typ, auch genannt string slice. Ein String-Slice hat eine feste Größe. Ein Literal-String wie let test = "hello world" hat den Typ 'static str. test ist eine Referenz zu diesem statisch allokierten String. &str kann nicht verändert werden, zum Beispiel,

let mut word = "hello world";
word[0] = 's';
word.push('\n');

str hat jedoch einen veränderbaren Slice &mut str, zum Beispiel: 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);

Aber eine kleine Änderung an UTF-8 kann die Byte-Länge ändern und ein Slice kann nicht auf sein Referenzobjekt umstellen.

13voto

00imvj00 Punkte 615

In einfachen Worten ist String ein Datentyp, der im Heap gespeichert ist (genauso wie Vec), und du hast Zugriff auf diesen Speicherort.

&str ist ein Slicetyp. Das bedeutet, es handelt sich nur um einen Verweis auf einen bereits vorhandenen String irgendwo im Heap.

&str führt keine Speicherzuweisung zur Laufzeit durch. Aus Gründen des Speichers kannst du also &str anstelle von String verwenden. Beachte jedoch, dass du bei der Verwendung von &str eventuell mit expliziten Lebensdauern umgehen musst.


10voto

Yilmaz Punkte 12859

In diesen 3 verschiedenen Typen

let noodles = "noodles".to_string();
let oodles = &noodles[1..];
let poodles = "_"; // dies ist ein String-Literal
  • Ein String hat einen änderbaren Puffer, der UTF-8-Text enthält. Der Puffer wird im Heap allokiert, sodass er seinen Puffer bei Bedarf oder auf Anforderung ändern kann. Im Beispiel ist "noodles" ein String, der einen acht Byte großen Puffer besitzt, von dem sieben Bytes genutzt werden. Man kann sich einen String als einen Vec vorstellen, der garantiert wohlgeformten UTF-8-Text enthält; tatsächlich ist dies die Implementierung von String.

  • Ein &str ist eine Referenz auf einen Lauf von UTF-8-Text, der von jemand anderem besessen wird: er "leiht" den Text. Im Beispiel ist oodles ein &str, der auf die letzten sechs Bytes des Textes von "noodles" verweist, und repräsentiert somit den Text "oodles." Wie andere Slice-Referenzen ist ein &str ein fat pointer, der sowohl die Adresse der tatsächlichen Daten als auch deren Länge enthält. Man kann sich einen &str einfach nur als einen &[u8] vorstellen, der garantiert wohlgeformten UTF-8-Text enthält.

  • Ein Stringliteral ist ein &str, der auf vorab allokierten Text verweist, der typischerweise im Nur-Lese-Speicher zusammen mit dem Maschinencode des Programms gespeichert ist. Im obenstehenden Beispiel ist poodles ein Stringliteral, das auf sieben Bytes zeigt, die beim Programmaufruf erstellt werden und bis zum Beenden des Programms erhalten bleiben.

So werden sie im Speicher gespeichert

enter image description here

Referenz: Programming Rust, von Jim Blandy, Jason Orendorff, Leonora F. S. Tindall

9voto

kn3l Punkte 18187

Einige Anwendungen

beispiel_1.rs

fn main(){
  let hello = String::("hello");
  let any_char = hello[0];//Fehler
}

beispiel_2.rs

fn main(){
  let hello = String::("hello");
  for c in hello.chars() {
    println!("{}",c);
  }
}

beispiel_3.rs

fn main(){
  let hello = String::("Strings sind cool");
  let any_char = &hello[5..6]; // = let any_char: &str = &hello[5..6];
  println!("{:?}",any_char);
}

Shadowing

fn main() {
  let s: &str = "hallo"; // &str
  let s: String = s.to_uppercase(); // String
  println!("{}", s) // HALLO
}

Funktion

fn say_hello(to_whom: &str) { //Typumwandlung
     println!("Hey {}!", to_whom) 
 }

fn main(){
  let string_slice: &'static str = "du";
  let string: String = string_slice.into(); // &str => String
  say_hello(string_slice);
  say_hello(&string);// &String
 }

Concat

 // String befindet sich auf dem Heap und kann in seiner Größe erhöht oder verkleinert werden
// Die Größe von &str ist festgelegt.
fn main(){
  let a = "Foo";
  let b = "Bar";
  let c = a + b; //Fehler
  // let c = a.to_string + b;
}

Beachten Sie, dass String und &str unterschiedliche Typen sind und dass Sie sich in 99% der Fälle nur um &str kümmern sollten.

7voto

Evgene Punkte 51

String ist ein Objekt.

&str ist ein Zeiger auf einen Teil des Objekts.

Bildbeschreibung hier eingeben

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X