# Области видимости и время жизни переменных в Rust

> Подробный разбор областей видимости (scopes) в Rust: блоки кода, передача владения, автоматическое освобождение ресурсов и предотвращение ошибок.

- **URL:** https://eagle2000.space/rust/rust-scope/
- **Date:** 2025-05-16

- **Tags:** rust, dev

---## Блоки и скоупы
{{< lead >}}
Подключим воображение чтобы лучше понять эту тему.
{{</ lead >}}

Итак, существует переменная со своей силой. Теперь представьте себе область видимости как некую территорию на которой эта переменная имеет силу.
В Rust такая территория называется скоупом (Scope). В этой статье мы поговорим о том, что такое скоуп/блоки и как это всё работает.



Блок (Block) - это область между открытыми и закрытыми фигурными скобками. Каждый раз, когда вы пишете фигурные скобки, например после названия функции:

```rust
fn hello() { {{< golink id="a1" />}}
   {{< golink id="a2" />}}
}
```

вы создаете новый блок {{< codelink id="a1" />}} . Все, что находится внутри этого блока  {{< codelink id="a2" />}} считается его областью видимости.


**Пример:**

Создадим переменную для хранения значения срабатывания датчика движения _от 0 до 100%_

```rust
fn main(){ {{< golink id="a3" />}}
    let move_sensor = 10;
}
```

Теперь зададим себе вопрос: в какой области эта переменная доступна? Ответом  будет: область видимости переменной move_sensor - главная функция {{< codelink id="a3" />}} `(main)`.

Стало чуть понятнее? Хорошо тогда движемся дальше.

### Вложенные скоупы

Что если мы хотим создать новый скоуп внутри функции `main`? Мы можем сделать это используя фигурные скобки:
```rust
fn main(){
    let move_sensor = 10;
    {
        {{< golink id="a4" />}}
    }
}
```

Мы создали новый блок - вложенная область видимости или вложенный контекст {{< codelink id="a4" />}} если сказать иначе.

### Взаимодействие между скоупами

Как я уже упоминал в прошлой статье [про затенение](../rust-shadowing/), внутренний скоуп может захватывать переменные из внешнего скоупа. Но в обратную сторону это не сработает. Вы не сможете объявить во внутреннем скоупе переменную и использовать её вне его границ.


### 💻 Области видимости и скоупы в Rust


#### Шаг 1

```rust
// ?compile_fail
fn main() {
    {
        let light_sensor = 20;
        println!("Внутри блока (light): {}", light_sensor);
    }
    // ❌ Ошибка компиляции: light_sensor больше не существует!
    println!("Вне блока (light): {}", light_sensor);
}
```

**Выход за границы области видимости**
- Переменная `light_sensor` объявлена внутри вложенного блока `{}`.
- За границами этого блока переменная уничтожается (освобождается память).
- Обращение к ней вне блока приводит к ошибке компиляции E0425.


#### Шаг 2

```rust
fn main() {
    let move_sensor = 10;
    {
        // Внутренний скоуп видит внешние переменные
        println!("Внутри блока (move): {}", move_sensor);
        let inner_sensor = 5;
        println!("Сумма в блоке: {}", move_sensor + inner_sensor);
    }
    println!("Вне блока (move): {}", move_sensor);
}
```

**Доступ к внешнему контексту**
- Вложенный блок имеет доступ к переменным внешнего скоупа (`move_sensor`).
- В обратную сторону (вынести `inner_sensor` наружу) это правило не работает.


При попытке использовать `light_sensor` за пределами фигурных скобок (как показано на Шаге 1) компилятор выдает ошибку `cannot find value 'light_sensor' in this scope`, потому что время жизни этой переменной закончилось на закрывающей фигурной скобке.

## Вывод

Вложенный скоуп можно представить как некий портал в который вы можете что-то принести, но вынести из него ничего нельзя. ✨

Важно запомнить, что:

- Переменные существуют внутри скоупа, в котором они объявлены.
- Внутренний скоуп может захватывать переменные из внешнего скоупа.
- Вы не можете использовать переменную вне ее скоупа.

Теперь вы знаете как правильно "готовить" области видимости в Rust! 😉


--- 


### 📝 Тест на знание областей видимости (Scope) в Rust


**1. Что происходит со значением при выходе управляющей переменной из области видимости (scope)?**

- [ ] Вызывается макрос panic!()
- [ ] Автоматически вызывается деструктор Drop и освобождается память
- [ ] Переменная сохраняется в глобальной памяти static
- [ ] Память очищает Garbage Collector

