TL; DR: หนึ่งสามารถใช้แทน&str
, &[T]
หรือ&T
เพื่อให้รหัสทั่วไปมากขึ้น
สาเหตุหลักประการหนึ่งที่ต้องใช้ a String
หรือ a Vec
เป็นเพราะอนุญาตให้เพิ่มหรือลดความจุได้ แต่เมื่อคุณยอมรับการอ้างอิงที่ไม่เปลี่ยนรูปคุณไม่สามารถใช้วิธีการใด ๆ ที่น่าสนใจผู้ที่อยู่ในหรือVec
String
ยอมรับ&String
, &Vec
หรือ&Box
ยังต้องมีการโต้แย้งที่จะได้รับการจัดสรรในกองก่อนที่คุณจะสามารถเรียกใช้ฟังก์ชัน ยอมรับ a &str
อนุญาตให้สตริงลิเทอรัล (บันทึกไว้ในข้อมูลโปรแกรม) และยอมรับ&[T]
หรือ&T
อนุญาตอาร์เรย์หรือตัวแปรที่จัดสรรสแต็ก การจัดสรรที่ไม่จำเป็นคือการสูญเสียประสิทธิภาพ โดยปกติจะปรากฏทันทีเมื่อคุณพยายามเรียกใช้วิธีการเหล่านี้ในการทดสอบหรือmain
วิธีการ:
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
พิจารณาผลการดำเนินงานก็คือว่า&String
, &Vec
และ&Box
แนะนำชั้นที่ไม่จำเป็นของร้ายที่คุณต้อง dereference &String
ที่จะได้รับString
และจากนั้นดำเนินการ dereference &str
ที่สองที่จะจบลงที่
คุณควรยอมรับstring slice ( &str
), slice ( &[T]
) หรือเพียงแค่ reference ( &T
) แทน &String
, &Vec<T>
หรือ&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();
}
}
&str
กว้างกว่า (เช่นเดียวกับ: กำหนดข้อ จำกัด น้อยลง) โดยไม่มีความสามารถลดลง"? นอกจากนี้: จุดที่ 3 มักจะไม่สำคัญเท่าที่ฉันคิด โดยปกติแล้วVec
s และString
s จะอาศัยอยู่บนสแต็กและมักจะอยู่ใกล้กับสแต็กเฟรมปัจจุบัน สแต็กมักจะร้อนและการแยกส่วนจะถูกเสิร์ฟจากแคชของ CPU