W Rust zasięg zmiennej jest ograniczony do bloku (klamrowego {}). Deklaracja nowej zmiennej o tej samej nazwie, co istniejąca w aktualnym lub zewnętrznym zasięgu, nazywana jest shadowing ("zacienianie"). Shadowing pozwala na zmianę typu i wartości zmiennej, nie naruszając koncepcji niemutowalności.
Przykład:
let x = 5; // x: i32 = 5 let x = x + 1; // x: i32 = 6 (zacienia starą x) let x = "hello"; // x: &str = "hello" (zmiana typu)
Shadowing nie wpływa na wydajność (to wyłącznie konstrukcja składniowa, kompilowana do różnych zmiennych na poziomie LLVM IR), ale może znacząco pogorszyć czytelność i utrzymanie kodu, zwiększając ryzyko błędów logicznych.
Pytanie: Czy shadowing zmiennej prowadzi do zwolnienia zasobów, jeśli poprzednia zmienna miała właściciela przydzielonej pamięci (na przykład, String)?
Często odpowiadają: Nie, ponieważ zmienna po prostu "przedefiniowana".
Poprawna odpowiedź: Tak, gdy zmienna jest zacieniana, stara wartość wychodzi z zasięgu, a jeśli posiadała zasób, jest wywoływana metoda Drop. To zapewnia poprawne zwolnienie pamięci.
Przykład:
let s = String::from("abc"); let s = 5; // String jest zwalniane tutaj (wywołana metoda Drop)
Historia
Młody programista użył shadowing dla jednej ze struktur z otwartym deskryptorem pliku i przez zacienienie zmiennej przed planowanym czasem, przypadkowo zamknął plik przed zakończeniem pracy. Prowadziło to do utraty danych w niektórych przypadkach.
Historia
W jednym projekcie badawczym shadowing był stosowany dla zmiennych na tym samym poziomie zagnieżdżenia, co często myliło programistów i prowadziło do odwołań do "starej" wartości zmiennej, myśląc, że jest ona aktualna.
Historia
W dużej aplikacji serwerowej ukryte shadowing pola struktury i zmiennej wewnątrz metody spowodowało nieoczywisty błąd, kiedy pole się nie zmieniało, a zmieniała się nowa lokalna zmienna o tej samej nazwie. Błąd został odkryty po długim poszukiwaniu przyczyn nieprawidłowego zachowania systemu.