TL; DR: Man kann stattdessen verwenden &str, &[T]oder &Tfür generischen Code zu ermöglichen.
Einer der Hauptgründe für die Verwendung von a Stringoder a Vecist, dass sie das Erhöhen oder Verringern der Kapazität ermöglichen. Wenn Sie jedoch eine unveränderliche Referenz akzeptieren, können Sie keine dieser interessanten Methoden für das Vecoder verwenden String.
Akzeptieren einer &String, &Vecoder &Boxauch erfordert das Argument auf dem Heap zugewiesen werden , bevor Sie die Funktion aufrufen kann. Das Akzeptieren von a &strermöglicht ein Zeichenfolgenliteral (in den Programmdaten gespeichert) und das Akzeptieren von a &[T]oder &Termöglicht ein vom Stapel zugewiesenes Array oder eine Variable. Eine unnötige Zuordnung ist ein Leistungsverlust. Dies wird normalerweise sofort angezeigt, wenn Sie versuchen, diese Methoden in einem Test oder einer mainMethode aufzurufen :
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
Eine weitere Leistung Überlegung ist , dass &String, &Vecund &Boxeine unnötige Schicht Indirektionsebene vorstellen , wie Sie das dereferenzieren haben &Stringeine zu bekommen Stringund dann eine zweite dereferenzieren ausführen , um am Ende an &str.
Stattdessen sollten Sie ein String-Slice ( &str), ein Slice ( &[T]) oder nur eine Referenz ( &T) akzeptieren . A &String, &Vec<T>oder &Box<T>wird automatisch in einen dazu gezwungen werden &str, &[T]oder &T, respectively.
fn awesome_greeting(name: &str) {
println!("Wow, you are awesome, {}!", name);
}
fn total_price(prices: &[i32]) -> i32 {
prices.iter().sum()
}
fn is_even(value: &i32) -> bool {
*value % 2 == 0
}
Jetzt können Sie diese Methoden mit einem breiteren Satz von Typen aufrufen. Zum Beispiel awesome_greetingkann mit einem String - Literal (genannt werden "Anna") oder einem zugeordneten String. total_pricekann mit einem Verweis auf ein Array ( &[1, 2, 3]) oder ein zugewiesenes aufgerufen werden Vec.
Wenn Sie Elemente zum Stringoder hinzufügen oder entfernen möchten Vec<T>, können Sie eine veränderbare Referenz ( &mut Stringoder &mut Vec<T>) verwenden:
fn add_greeting_target(greeting: &mut String) {
greeting.push_str("world!");
}
fn add_candy_prices(prices: &mut Vec<i32>) {
prices.push(5);
prices.push(25);
}
Speziell für Slices können Sie auch ein &mut [T]oder akzeptieren &mut str. Auf diese Weise können Sie einen bestimmten Wert innerhalb des Slice mutieren, aber Sie können die Anzahl der Elemente innerhalb des Slice nicht ändern (was bedeutet, dass dies für Zeichenfolgen sehr eingeschränkt ist):
fn reset_first_price(prices: &mut [i32]) {
prices[0] = 0;
}
fn lowercase_first_ascii_character(s: &mut str) {
if let Some(f) = s.get_mut(0..1) {
f.make_ascii_lowercase();
}
}
&strist allgemeiner (wie in: weniger Einschränkungen auferlegt) ohne eingeschränkte Fähigkeiten"? Außerdem: Punkt 3 ist meiner Meinung nach oft nicht so wichtig. Normalerweise lebenVecs undStrings auf dem Stapel und oft sogar irgendwo in der Nähe des aktuellen Stapelrahmens. Der Stack ist normalerweise heiß und die Dereferenzierung wird aus einem CPU-Cache bereitgestellt.