Как обратиться к внешней локальной переменной?

Я знаю, что можно обратиться к глобальной переменной таким способом:

int i = 10;
int main() 
{
    for (int i = 0; i < 10; i++)
    {
        for (int i = ::i; i < 10; i++)
        {

        }
    }
}

Можно ли сделать то же самое, но для внешней локальной?


Ответы (2 шт):

Автор решения: Eugene X

Если ты имеешь ввиду 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;              

Ситуация, описанная выше, могла родиться по такой схеме:

  1. Написали функцию без переменной ret внутреннего блока (I). В (R) происходит изменение переменной уровня (O). Всё ок.
  2. Кто-то другой (и ты сам через пару месяцев) добавил переменную ret во внутренний блок (I) для исключительно локального использования в блоке (например, отладить какую-то функцию). И теперь в (R) происходит изменение другой переменной. Фейл.

Ошибки такого рода не всегда просто заметить, обычно к ним приводит использование простых и популярных имён типа (i, ret, var, enabled ... ). К счастью, для обнаружения подобных ситуаций в компиляторах есть соответствующие опции, порождающие предупреждение, например, -Wshadow для gcc.

→ Ссылка