Как обратиться к внешней локальной переменной?
Я знаю, что можно обратиться к глобальной переменной таким способом:
int i = 10;
int main()
{
for (int i = 0; i < 10; i++)
{
for (int i = ::i; i < 10; i++)
{
}
}
}
Можно ли сделать то же самое, но для внешней локальной?
Ответы (2 шт):
Если ты имеешь ввиду int i = 10; после того как ты её дважды переобъявил, нет! Конечно нельзя! Но в твоём примере ты использовал root namespace.
namespace {
int i = 10;
}
// Таким образом ::i `int(10)` будет доступна
::i
namespace myNamespace {
int i = 10;
}
myNamespace::i
В принципе таким образом весь namespace std { ... } описан. Как основные методы/переменные C++.
Имя локальной переменной внешнего блока будет перекрываться переменной внутреннего блока. Какого-то специального синтаксиса (вроде разрешения области видимости :: для доступа к именам из других пространств имён) не существует.
Можно, конечно, завести дополнительную ссылочную переменную, через которую будет доступ. Но выглядит это странно, проще сразу дать разные имена:
for (int i = 0; i < 10; i++) {
auto& r = i;
for (int i = 0; i < 10; i++) {
// i из внешнего цикла доступна через r
Вообще, практика использования одинаковых локальных имён с сокрытием на разных уровнях достаточно порочна, лучше этого избегать, чтобы не порождать ситуации, когда думаешь, что во внутреннем блоке работаешь со внешней переменной. Например:
int ret = 0; // внешний уровень (O)
// ...
{
int ret = 100500; // внутренний уровень (I)
// ...
ret = 42; // хочешь изменить переменную внешнего уровня (R)
// ...
}
return ret;
Ситуация, описанная выше, могла родиться по такой схеме:
- Написали функцию без переменной
retвнутреннего блока (I). В (R) происходит изменение переменной уровня (O). Всё ок. - Кто-то другой (и ты сам через пару месяцев) добавил переменную
retво внутренний блок (I) для исключительно локального использования в блоке (например, отладить какую-то функцию). И теперь в (R) происходит изменение другой переменной. Фейл.
Ошибки такого рода не всегда просто заметить, обычно к ним приводит использование простых и популярных имён типа (i, ret, var, enabled ... ). К счастью, для обнаружения подобных ситуаций в компиляторах есть соответствующие опции, порождающие предупреждение, например, -Wshadow для gcc.