Область видимости (scope) переменной — часть кода, из которой возможен обычный доступ к переменной по её имени. Отвечает на вопрос «где имя обозначает именно этот объект».
Зачем нужно
Будет ли ошибка?
int x = 0;
int main() {
int x = 1;
std::cout << x << '\n';
return 0;
}Нет, программа выведет 1. Две переменные с одним именем существуют
одновременно, и правила видимости решают, какую из них обозначает x
в каждой строке.
Как работает
Видимость не больше, чем существование
Область видимости не может быть больше области действия:
нельзя увидеть по имени объект, который уже не существует. Но может быть
меньше. В примере выше глобальная x продолжает существовать во время
выполнения main, но локальная переменная с тем же именем скрывает
глобальное имя.
Поиск от внутреннего к внешнему
По умолчанию поиск имени идёт от наиболее вложенной области к менее вложенной:
int x = 0;
int main() {
int x = 1;
{
int x = 2;
std::cout << x << '\n'; // 2
}
return 0;
}Компилятор сначала ищет x в самом внутреннем блоке, находит int x = 2; и
использует её.
Операция ::
Чтобы обратиться именно к глобальной переменной, есть операция разрешения
области видимости ::. Она говорит компилятору: искать имя нужно в глобальной
области.
int x = 0;
int main() {
int x = 1;
{
int x = 2;
std::cout << x << '\n'; // 2
std::cout << ::x << '\n'; // 0
}
return 0;
}Тонкости
- К промежуточной локальной
x = 1по имени из внутреннего блока обратиться нельзя: внутренняяxеё скрывает, а::xведёт сразу в глобальную область. - Скрытие имени — не ошибка компиляции. Программа соберётся и молча будет работать с другой переменной.
- Два вопроса не смешивать: область действия — где объект
существует; область видимости — где объект доступен по имени. Иногда они
почти совпадают (одна локальная переменная в
main), иногда объект существует, а имя временно скрыто.
Частые ошибки
- Завести во вложенном блоке переменную с тем же именем, что снаружи, и ожидать, что изменения попадут во внешнюю.
- Думать, что
::xозначает «переменная на уровень выше». Она означает «глобальная переменная».