수명(Lifetime)
- 참조는 어디까지 유효할 것인가? 이 것을 표현하는 개념이 수명
- 기본적으로 컴파일러가 추론한다.
- 하지만 함수의 인자로 사용되는 참조 같은 경우, 컴파일러가 명시적으로 참조의 수명을 알 수 없어 죽은 참조가 생길 위험이 있다.
- 그를 위해 명시적으로 수명을 표시한다.
#![allow(unused)] fn main() { &i32 //참조 &'a i32//수명 매개변수 'a를 가지는 참조 &'a mut i32 //가변이 가능하고 수명 매개변수 'a를 가지는 참조 }
함수에서 사용
#![allow(unused)] fn main() { fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } }
이 애노테이션의 의미
- 함수의 입력값
x
,y
는 최소한 수명'a
동안 유효하다. - 이 함수의 리턴 값(참조)는 수명
'a
를 가진다.
리턴 타입의 수명 매개변수는 입력된 매개변수의 수명 매개변수와 같아야 한다. 그러지 않으면 함수가 끝나는 순간 함수에서 반환된 참조는 죽은 참조가 될 것이다.
구조체에 참조 저장하기
구조체에도 참조를 저장할 수 있다. 그렇지만 구조체에 들어가는 참조의 수명이 보장되어야 죽은 참조를 피할 수 있으므로, 수명 매개변수를 작성해야 한다.
struct ImportantExcerpt<'a> { part: &'a str, } impl<'a> ImportantExcerpt<'a> { fn level(&self) -> i32 { 3 } } fn main() { let novel = String::from("Call me Ishmael. Some years ago..."); let first_sentence = novel.split('.') .next() .expect("Could not find a '.'"); let i = ImportantExcerpt { part: first_sentence }; }
수명 매개변수의 생략
- 그렇지만 모든 참조를 사용하는 상황에서 수명을 명시해야 하는 것이 아니다.
- 다음 3가지 규칙에 따라, 컴파일러는 자동으로 수명을 짐작한다.
- 각 참조는 각각의 수명 매개변수가 존재해야 한다.
- 명시적으로 하나의 입력 수명 매개변수가 있으면, 입력 수명을 모든 출력 수명 매개변수에 사용한다.
- 입력 수명 매개변수가 하나 이상이며, 함수가 메서드인 경우,
self
의 수명을 모든 출력 변수에 적용한다.
- 이 규칙으로도 수명을 알수 없는 참조의 경우, 컴파일 에러가 발생하게 된다.
정적 수명
- 참조를 전역에서 사용될 수 있게 하는 수명
- 권장되지 않음
#![allow(unused)] fn main() { let s: &'static str = "이 문자열은 정적 수명을 가집니다.'; }