수명

2025. 3. 16. 12:20기타

https://rinthel.github.io/rust-lang-book-ko/ch10-03-lifetime-syntax.html

 

라이프타임을 이용한 참조자 유효화 - The Rust Programming Language

이 문서는 2판 번역본입니다. 최신 2021 에디션 문서는 https://doc.rust-kr.org 에서 확인하실 수 있습니다. 4장에서 참조자에 대한 이야기를 할 때, 중요한 디테일을 한 가지 남겨두었습니다: 러스트에

rinthel.github.io

 

우선

제네릭에 대한 설명

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

fn main() {
    let p = Point { x: 5, y: 10 };

    println!("p.x = {}", p.x());
}

위와 같이 impl<T>로 명시하지 않으면, Point 뒤에 <T>를 알지 못하여 error!

impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

구체적인 타입이 있다면 가능

좋은 소식은, 제네릭 타입의 사용이 구체적인 타입을 사용했을 때와 비교해서 전혀 느려지지 않는다는 것

러스트는 컴파일 타임에 제네릭을 사용하는 코드를 단형성화 (monomorphization) 함

컴파일러는 제네릭 코드가 호출된 곳을 전부 찾고, 제네릭 코드가 호출될 때 사용된 구체 타입으로 코드를 생

 

 

라이프타임

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

 

두 매개변수를 갖고 둘 다 적어도 라이프타임 'a만큼 살아있는 문자열 슬라이스 이며, 반환하는 문자열 슬라이스도 라이프타임 'a만큼 살아있다는 정보를 줌

longest 함수가 반환하는 참조자의 라이프타임은 함수 인수로서 참조된 값들의 라이프타임 중 작은 것과 동일하다는 의미

longest 함수에 구체적인 참조자들이 넘겨질 때 'a에 대응되는 구체적인 라이프타임은 x 스코프와 y 스코프가 겹치는 부분입니다. 바꿔 말하면, x 라이프타임과 y 라이프타임 중 더 작은 쪽이 제네릭 라이프타임 'a의 구체적인 라이프타임이 됩니다.

이 함수를 정의하는 시점에서는 함수가 전달받을 구체적인 값을 알 수 없고, 

전달받은 참조자의 구체적인 라이프타임도 알 수 없습니다. 

 

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!("The longest string is {}", result);
}

string2의 유효성이 훨씬 짧아, result 같은 경우, 컴파일러는 컴파일 타임에 string2가 짧은 걸 모른다.

이로인해 유효하지 않은, dangling 이 될 위험이 있다고 보는 것.

이러한 경우 때문에 라이프타임 매개변수 'a를 명시하는 것

-> error!

 

fn longest<'a>(x: &'a str, y: &str) -> &'a str {
    x
}

위의 경우에는 x의 유효성만 검증하면 되므로, x만 lifetime 매개변수 'a를 명시

 

fn longest<'a>(x: &str, y: &str) -> &'a str {
    let result = String::from("really long string");
    result.as_str()
}

위의 경우 댕글링 포인터인 참조만 남는다.

-> error!

 

 

구조체

struct User {
    active: bool,
    username: &str,
    email: &str,
    sign_in_count: u64,
}

fn main() {
    let user1 = User {
        active: true,
        username: "someusername123",
        email: "someone@example.com",
        sign_in_count: 1,
    };
}

라이프타임이 명시돼야 한다며 컴파일러가 에러를 일으킬 겁니다.

 

이유는, 구조체에서 참조하는 대상이 구조체보다 먼저 소멸해서는 안되기 때문

 

struct User {
    active: bool,
    username: &str,
    email: &str,
    sign_in_count: u64,
}

fn main() {
    let user1 = User {
        active: true,
        username: "someusername123",
        email: "someone@example.com",
        sign_in_count: 1,
    };
}

 

라이프타임 생략 규칙

  • 첫 번째 규칙: 함수의 매개변수에 하나의 라이프타임이 있을 때, 해당 라이프타임을 출력 라이프타임에 적용합니다. 예를 들어, fn first_word<'a>(s: &'a str) -> &'a str와 같은 경우, 매개변수 s의 라이프타임을 반환 값에도 사용합니다.
  • 두 번째 규칙: 만약 입력 라이프타임 매개변수가 하나만 있으면, 해당 라이프타임이 모든 출력 라이프타임에 적용됩니다.
  • 세 번째 규칙: &self나 &mut self가 메서드의 입력으로 있을 경우, self의 라이프타임이 출력 라이프타임에 적용됩니다.

 

정적 라이프타임

static 라이프타임은 꽤 간단했는데요. 라이프타임이 프로그램 전체 생애 동안 살아있는 경우 사용합니다.

'static 이렇게 사용합니다.

let s: &'static str = "blah blah"

 

 

 

flow 요약

1. dangling 참조 방지가 주 목적

스코프를 나감으로써 유효성은 소멸하여, 참조만 남는 것을 방지 하기 위한 lifetime이 존재함.

 

1. 함수나 구조체에서 발생 하며, 함수 매개변수와 반환값에서 참조를 하거나, 구조체의 필드값의 속성으로 참조가 들어갈 때 발생

 

why? 컴파일러는 컴파일 타임에 참조가 유효한지 아닌지를 알 수 없음

이 때문에, 'a 라는 것으로 최소한 해당 함수 동안은 살아있음을 명시해야 함

또는 구조체의 참조보다 그것의 유효성을 참조한 것이 더 오래 살아야함을 명시.

'a로 명시하면, 컴파일러는 참조에서 유효성이 있는지를 확인함.

 

 

<'a>: 제네릭의 한 종류, 'b도 가능

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'기타' 카테고리의 다른 글

Rust study  (0) 2025.03.16
백업용 링크  (2) 2024.09.07
BoB 12기 보안제품개발 트랙 회고  (1) 2024.03.24