Struktury w Rust mogą przechowywać odwołania do innych obiektów poprzez wskazanie jawnych czasów życia (lifetimes) w definicji struktury. Jest to wymagane, aby kompilator mógł sprawdzić, że żadne odwołanie nie stanie się nieważne. Oto przykład:
struct Book<'a> { title: &'a str, author: &'a str, }
Tutaj struktura Book zawiera dwa odwołania o tym samym czasie życia 'a. Kiedy piszesz funkcję zwracającą taką strukturę, musisz zapewnić, że wszystkie odwołania w niej będą ważne niezależnie od wewnętrznej logiki funkcji:
fn book_factory<'a>(title: &'a str, author: &'a str) -> Book<'a> { Book { title, author } }
Jeśli spróbujesz zwrócić z funkcji strukturę, w której pola-odwołania wskazują na lokalne zmienne tej funkcji, wystąpi błąd kompilacji, ponieważ czas życia odwołań jest niewystarczający do bezpiecznego dostępu.
Czy można stworzyć strukturę, która w jednym z pól zawiera odwołanie (&str), a w drugim — String? Dlaczego to może być problemem?
Często błędna odpowiedź: "Tak, można, to jest bezpieczne".
W rzeczywistości, jeśli &str zostało uzyskane z String, a struktura przetrwa ten String, odwołanie stanie się wiszącą referencją (dangling reference). Na przykład:
struct Test<'a> { s1: &'a str, s2: String, } fn main() { let s = String::from("hello"); let t = Test { s1: &s, s2: s }; // t.s1 jest właściwie bezpieczna, tylko dopóki s2 (s) żyje, ale jeśli s2 zostanie usunięte jako pierwsze — błąd }
Historia W jednym z projektów próbowano zwrócić z funkcji ładującej strukturę zawierającą odwołanie do tymczasowego ciągu znaków utworzonego wewnątrz tej samej funkcji. Kod nie został skompilowany, potrzebne było znaczące przepisanie, aby usunąć czas życia zmiennej lokalnej.
Historia Programista zamierzał użyć struktury z odwołaniem do elementu tablicy utworzonej w funkcji, ale po zwrocie to odwołanie okazało się nieważne, co kompilator skutecznie zapobiegł.
Historia W projekcie korporacyjnym programiści przechowywali odwołanie &str do ciągu znaków z innego obiektu, który został usunięty z kolekcji wcześniej niż samo odwołanie — przy późniejszym dostępie do tego odwołania wystąpił panic.