Rust 라이프타임(Lifetimes)은 참조의 유효 범위를 컴파일 시 추적하여 use-after-free, dangling pointer 등을 방지한다. 소유권 시스템의 핵심 요소다.
라이프타임 기본
rust
// 라이프타임 어노테이션: 'a 형태
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
let s1 = String::from("long string");
let result;
{
let s2 = String::from("xy");
result = longest(s1.as_str(), s2.as_str());
println!("{}", result); // OK: result는 s2의 수명 내에 있음
}
// println!("{}", result); // Error: s2가 이미 해제됨
구조체의 라이프타임
rust
struct Important<'a> {
part: &'a str, // 'a만큼 살아있는 str 참조
}
impl<'a> Important<'a> {
fn announce(&self) -> &str {
self.part
}
}
let novel = String::from("Call me Ishmael...");
let first = novel.split('.').next().expect("no period");
let i = Important { part: first }; // novel이 살아있는 동안 유효
라이프타임 생략 규칙
rust
// 컴파일러가 자동으로 추론하는 3가지 규칙
// 1. 입력 참조마다 다른 라이프타임 할당
// 2. 입력이 하나면 출력도 같은 라이프타임
// 3. &self, &mut self가 있으면 출력은 self의 라이프타임
fn first_word(s: &str) -> &str { // 생략된 형태
s.split_whitespace().next().unwrap_or("")
}
// 실제: fn first_word<'a>(s: &'a str) -> &'a str
'static 라이프타임
rust
// 프로그램 전체 수명
let s: &'static str = "I have a static lifetime";
// 제네릭 바운드에서의 'static
fn keep<T: 'static>(val: T) -> Box<dyn std::any::Any> {
Box::new(val) // 소유된 타입이므로 'static 만족
}
관련 개념