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 |