English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Rust의 라이프스타일 메커니즘은 소유권 메커니즘과 동일한 중요한 자원 관리 메커니즙입니다.
이 개념을 도입한 이유는 복잡한 타입 시스템에서 자원 관리 문제를 해결하기 위해서입니다.
복잡한 타입에 대한 처리에는 필수적인 메커니즘입니다. 왜냐하면 복잡한 타입의 데이터는 처리기에 쉽게 복사되거나 계산될 수 없기 때문입니다.
문헌 참조는 매우 복잡한 자원 관리 문제를 초래할 수 있으며, 먼저 하중 참조를 이해해보겠습니다:
{ let r; { let x = 5; r = &x; } println!("r: {}", r); }
이 코드는 Rust 컴파일러를 통과하지 않습니다. 이유는 r가 참조하는 값을 사용하기 전에 이미 해제된 것입니다.
위 그림에서 초록색 범위 'a는 r의 생명주기를 나타내며, 파란색 범위 'b는 x의 생명주기를 나타냅니다. 명백히 'b는 'a보다 훨씬 작기 때문에, 참조는 값을의 생명주기 내에서만 유효해야 합니다。
우리는 구조체에서 String을 사용하지 않고 &str을 사용합니다. 이유를 예제로 설명하겠습니다:
fn longer(s1: &'str, s2: &'str) -> &str { if s2.len() > s1.len() { s2 } else { s1 } }
longer 함수는 s1 와 s2 두 문자열 슬라이스 중 더 긴 것이 참조 값을 반환합니다. 하지만 이 코드만으로는 컴파일되지 않으며, 반환 값 참조가 만료된 참조를 반환할 수 있다는 이유입니다:
fn main() { let r; { let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); } println!("{}는 더 길다", r); }
이 프로그램에서 비교가 이루어졌지만, r가 사용될 때 소스 값 s1 와 s2 는 모두 무효가 되었습니다. 물론 r의 사용을 s1 와 s2 의 생명주기 범위 내에서 이러한 오류가 발생하지 않도록 방지하지만, 함수는 자신을 벗어난 다른 부분의 상태를 알 수 없기 때문에, 자신이 전달하는 값을 정상적인 것으로 보장하기 위해 모든 위험을 제거하기 위해 소유권 원칙을 선택해야 하므로, longer 함수는 컴파일할 수 없습니다。
생명주기 주석은 참조의 생명주기를 설명하는 방법입니다。
이렇게 하면 참조의 생명주기는 변경되지 않지만, 적절한 위치에서 두 참조의 생명주기가 일치하는 것을 선언할 수 있습니다。
생명주기 주석은 단락 기호로 시작하고, 그 다음에 소문자 단어를 따릅니다:
&i32 // 일반 참조 &'a i32 // 생명주기 주석을 포함한 참조 &'a mut i32 // 생명주기 주석을 포함한 가변형 참조
longer 함수를 생명주기 주석으로 수정해 보겠습니다:
fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str { if s2.len() > s1.len() { s2 } else { s1 } }
생명주기 이름을 규범화하기 위해 템플릿 제네릭을 사용해야하며, 그런 다음 함수 반환 값의 생명주기는 두 파라미터의 생명주기와 일치하므로 호출할 때 이렇게 작성할 수 있습니다:
fn main() { let r; { let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); println!("{}는 더 길다", r); } }
이 두 부분의 프로그램을 결합하여 실행된 결과:
ecmascript는 더 길다
주의:자동 타입 판단 원칙을 잊지 마세요。
이전에 남겨둔 의문에 대한 답변을 여기서 해결합니다:
fn main() { struct Str<'a> {} content: &'a str } let s = Str { content: "string_slice" }; println!("s.content = {}", s.content); }
실행 결과:
s.content = string_slice
Str 구조체에 메서드 정의가 있는 경우:
impl<'a> Str<'a> { fn get_content(&self) -> &str { self.content } }
반환 값에는 생명 주기 주석이 없지만, 추가할 필요도 없습니다. 이는 역사적 문제입니다. 초기 Rust는 생명 주기 자동 판단을 지원하지 않았으며, 모든 생명 주기는 엄격하게 선언되어야 했습니다. 하지만 현재의 주류 안정 버전의 Rust는 이 기능을 지원합니다.
생명 주기 주석은 특별한 것입니다: 'static. 모든 따옴표로 포함된 문자열 상수는 정확한 데이터 타입이며, &'static str입니다. 'static은 프로그램 실행 시작부터 실행 종료까지의 생명 주기를 의미합니다.
use std::fmt::Display; fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str where T: Display { println!("공지! {}", ann); if x.len() > y.len() { x } else { y } }
이 프로그램은 Rust 성경에서 출발한 프로그램이며, 일반화, 특성, 생명 주기 기계를 동시에 사용한 프로그램입니다. 강요하지 않습니다. 체험해보세요. 결국 필요할 것입니다!