TL;DR: 代わりに&str
,&[T]
または&T
を使用して、より一般的なコードを使用できます。
String
aまたは aを使用する主な理由の 1 つはVec
、容量を増減できるからです。ただし、不変の参照を受け入れると、これらの興味深いメソッドをVec
またはで使用することはできませんString
。
またはを受け入れるには&String
、関数を呼び出す前に引数をヒープに割り当てる必要があります。a を受け入れると(プログラム データに保存された) 文字列リテラルが許可され、orを受け入れるとスタック割り当ての配列または変数が許可されます。不必要な割り当ては、パフォーマンスの損失です。これは通常、テストまたはメソッドでこれらのメソッドを呼び出そうとするとすぐに明らかになります。&Vec
&Box
&str
&[T]
&T
main
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
パフォーマンスに関するもう 1 つの考慮事項は&String
、を取得するために を参照解除し、最終的に を取得するために 2 番目の参照解除を実行する必要があるため、不要な間接参照層を導入すること&Vec
です。&Box
&String
String
&str
代わりに、文字列スライス( &str
)、スライス( &[T]
)、または単なる参照 ( )を受け入れる必要があります&T
。&String
、&Vec<T>
またはは、それぞれ ( deref coercionを介して) 、またはに&Box<T>
自動的に強制されます。&str
&[T]
&T
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
}
これらのメソッドをより幅広いタイプのセットで呼び出すことができるようになりました。たとえば、文字列リテラル ( )または割り当てられawesome_greeting
た で呼び出すことができます。配列 ( )または割り当てられた への参照を使用して呼び出すことができます。"Anna"
String
total_price
&[1, 2, 3]
Vec
String
またはから項目を追加または削除したい場合は、変更可能な参照(または)Vec<T>
を取得できます。&mut String
&mut Vec<T>
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);
}
&mut [T]
特にスライスの場合、またはを受け入れることもできます&mut str
。これにより、スライス内の特定の値を変更できますが、スライス内のアイテムの数を変更することはできません (つまり、文字列に対して非常に制限されています)。
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();
}
}