Rust의 구조체는 구조체 정의에서 명시적 생명 주기(lifetimes)를 지정하여 다른 객체에 대한 참조를 저장할 수 있습니다. 이는 컴파일러가 어떤 참조도 무효화되지 않도록 확인할 수 있도록 하기 위함입니다. 다음은 예시입니다:
struct Book<'a> { title: &'a str, author: &'a str, }
여기서 구조체 Book은 동일한 생명 주기 'a를 가진 두 개의 참조를 포함합니다. 이러한 구조체를 반환하는 함수를 작성할 때, 함수의 내부 로직과 무관하게 모든 참조가 유효하다는 것을 보장해야 합니다:
fn book_factory<'a>(title: &'a str, author: &'a str) -> Book<'a> { Book { title, author } }
만약 함수에서 구조체를 반환하려고 할 때 필드 참조가 예를 들어 그 함수의 지역 변수들을 가리킨다면, 참조의 생명 주기가 안전한 접근을 위해 충분하지 않기 때문에 컴파일 오류가 발생합니다.
하나의 필드에 참조 (&str)를 포함하고 다른 필드에 String을 포함하는 구조체를 만들 수 있습니까? 이것이 문제가 될 수 있는 이유는 무엇입니까?
종종 잘못된 답변: "네, 가능합니다. 안전합니다".
실제로, &str이 String에서 가져온 것이라면, 구조체가 그 String보다 오래 지속되므로 참조가 무효(reference)가 됩니다. 예를 들어:
struct Test<'a> { s1: &'a str, s2: String, } fn main() { let s = String::from("hello"); let t = Test { s1: &s, s2: s }; // t.s1은 실제로 s2(s)가 살아 있는 동안만 안전하지만, s2가 먼저 제거되면 — 오류 }
이야기 한 프로젝트에서 로컬 함수 내에서 생성된 임시 문자열에 대한 참조를 포함하는 구조체를 반환하려고 했으나, 코드를 컴파일할 수 없었고, 로컬 변수의 생명 주기를 제거하기 위한 상당한 수정이 필요했습니다.
이야기 개발자는 함수에서 생성된 배열 요소에 대한 참조를 가진 구조체를 사용하려고 했으나, 반환 후 그 참조가 유효하지 않게 되어 컴파일러가 이를 성공적으로 방지했습니다.
이야기 기업 프로젝트에서 개발자들은 컬렉션에서 다른 객체의 문자열에 대한 &str 참조를 저장했지만, 그 후 해당 문자열이 삭제되었고, 이 참조에 접근하려 할 때 panic이 발생했습니다.