Lifetimes
Lifetimes คืออะไร
หัวข้อที่มีชื่อว่า “Lifetimes คืออะไร”Lifetime คือแนวคิดที่บอก compiler ว่า reference จะยังคง valid อยู่นานแค่ไหน ใน Rust ทุก reference มี lifetime แต่ในหลายกรณี compiler สามารถอนุมานได้เองโดยไม่ต้องเขียนอย่างชัดเจน
จุดประสงค์หลักคือการป้องกัน dangling reference — situation ที่ reference ชี้ไปยังหน่วยความจำที่ถูก free ไปแล้ว
Lifetime Annotation Syntax
หัวข้อที่มีชื่อว่า “Lifetime Annotation Syntax”Lifetime parameter เขียนด้วย apostrophe ตามด้วยชื่อ เช่น 'a, 'b และต้องประกาศใน angle bracket เหมือน generic:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y }}'a ที่นี่หมายความว่า “return value มีชีวิตอยู่อย่างน้อยนานเท่ากับ reference ที่สั้นกว่าระหว่าง x และ y”
Lifetimes ใน Structs
หัวข้อที่มีชื่อว่า “Lifetimes ใน Structs”เมื่อ struct เก็บ reference จะต้องมี lifetime annotation:
struct Excerpt<'a> { text: &'a str,}นี่บอก compiler ว่า instance ของ Excerpt ต้องมีชีวิตอยู่ไม่นานกว่า text ที่ชี้ไป
Lifetime Elision
หัวข้อที่มีชื่อว่า “Lifetime Elision”ในหลายกรณีทั่วไป Rust มี elision rules ที่ช่วยให้คุณละ lifetime annotation ได้ เช่น:
// คุณเขียนแบบนี้:fn first_word(s: &str) -> &str { ... }
// Compiler เห็นเป็นแบบนี้:fn first_word<'a>(s: &'a str) -> &'a str { ... }Elision rules ครอบคลุมกรณีที่พบบ่อยที่สุด ทำให้ code สะอาดขึ้นโดยไม่สูญเสียความปลอดภัย
'static Lifetime
หัวข้อที่มีชื่อว่า “'static Lifetime”'static คือ lifetime พิเศษที่หมายความว่า reference มีชีวิตอยู่ตลอด duration ของ program:
let s: &'static str = "I have a static lifetime.";String literal ทุกอันมี 'static lifetime เพราะถูก embed อยู่ใน binary ของ program
ลองเล่น
หัวข้อที่มีชื่อว่า “ลองเล่น”Playground ด้านล่างแสดง function longest พร้อม lifetime annotation และ struct Excerpt ที่เก็บ reference — ลองดูว่า borrow checker รับประกันความถูกต้องของ reference อย่างไร
// A function with a lifetime annotation:// the returned reference lives at least as long as the shorter of x or y.fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y }}
// A struct that holds a reference — must annotate the lifetime.struct Excerpt<'a> { text: &'a str,}
impl<'a> Excerpt<'a> { fn announce(&self) -> &str { self.text }}
fn main() { let string1 = String::from("long string is long"); let result; { let string2 = String::from("xyz"); result = longest(string1.as_str(), string2.as_str()); println!("longest: {}", result); }
let novel = String::from("Call me Ishmael. Some years ago..."); let first_sentence = novel.split('.').next().expect("Could not find '.'"); let excerpt = Excerpt { text: first_sentence }; println!("excerpt: {}", excerpt.announce());}Compiling…