TL; DR: Seseorang dapat menggunakan &str
, &[T]
atau &T
untuk mengizinkan kode yang lebih umum.
Salah satu alasan utama menggunakan a String
atau a Vec
adalah karena memungkinkan peningkatan atau penurunan kapasitas. Namun, saat Anda menerima referensi yang tidak dapat diubah, Anda tidak dapat menggunakan salah satu metode menarik tersebut di Vec
atau String
.
Menerima a &String
, &Vec
atau &Box
juga membutuhkan argumen untuk dialokasikan di heap sebelum Anda dapat memanggil fungsi tersebut. Menerima a &str
memungkinkan string literal (disimpan dalam data program) dan menerima &[T]
atau &T
mengizinkan array atau variabel yang dialokasikan tumpukan. Alokasi yang tidak perlu adalah hilangnya kinerja. Ini biasanya langsung terungkap saat Anda mencoba memanggil metode ini dalam pengujian atau main
metode:
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
Pertimbangan kinerja lainnya adalah itu &String
, &Vec
dan &Box
memperkenalkan lapisan tipuan yang tidak perlu karena Anda harus melakukan dereferensi &String
untuk mendapatkan String
dan kemudian melakukan dereferensi kedua untuk berakhir di &str
.
Sebagai gantinya, Anda harus menerima string slice ( &str
), slice ( &[T]
), atau hanya referensi ( &T
). A &String
, &Vec<T>
atau &Box<T>
akan secara otomatis dipaksa menjadi &str
, &[T]
atau &T
, masing-masing.
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
}
Sekarang Anda dapat memanggil metode ini dengan kumpulan tipe yang lebih luas. Misalnya, awesome_greeting
dapat dipanggil dengan string literal ( "Anna"
) atau dialokasikan String
. total_price
bisa dipanggil dengan referensi ke array ( &[1, 2, 3]
) atau yang dialokasikan Vec
.
Jika Anda ingin menambah atau menghapus item dari String
atau Vec<T>
, Anda dapat menggunakan referensi yang dapat diubah ( &mut String
atau &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);
}
Khusus untuk irisan, Anda juga dapat menerima &mut [T]
atau &mut str
. Ini memungkinkan Anda untuk mengubah nilai tertentu di dalam slice, tetapi Anda tidak dapat mengubah jumlah item di dalam slice (yang artinya sangat dibatasi untuk string):
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();
}
}
&str
lebih umum (seperti: memberlakukan lebih sedikit batasan) tanpa mengurangi kemampuan"? Juga: poin 3 seringkali tidak terlalu penting menurut saya. BiasanyaVec
s danString
s akan hidup di stack dan bahkan sering berada di dekat frame stack saat ini. Tumpukan biasanya panas dan dereferensi akan disajikan dari cache CPU.