수명(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
    }
}
}

이 애노테이션의 의미

  1. 함수의 입력값 x, y는 최소한 수명 'a동안 유효하다.
  2. 이 함수의 리턴 값(참조)는 수명 '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가지 규칙에 따라, 컴파일러는 자동으로 수명을 짐작한다.
  1. 각 참조는 각각의 수명 매개변수가 존재해야 한다.
  2. 명시적으로 하나의 입력 수명 매개변수가 있으면, 입력 수명을 모든 출력 수명 매개변수에 사용한다.
  3. 입력 수명 매개변수가 하나 이상이며, 함수가 메서드인 경우, self의 수명을 모든 출력 변수에 적용한다.
  • 이 규칙으로도 수명을 알수 없는 참조의 경우, 컴파일 에러가 발생하게 된다.

정적 수명

  • 참조를 전역에서 사용될 수 있게 하는 수명
  • 권장되지 않음

#![allow(unused)]
fn main() {
let s: &'static str = "이 문자열은 정적 수명을 가집니다.';
}