Урок №15. Локальная область видимости

  Юрий  | 

  |

  Обновл. 11 Сен 2021  | 

 108337

 ǀ   20 

Как мы уже знаем из предыдущих уроков, при выполнении процессором стейтмента int х; создается переменная. Возникает вопрос: «Когда эта переменная уничтожается?».

Область видимости переменной определяет, кто может видеть и использовать переменную во время её существования. И параметры функции, и переменные, которые объявлены внутри функции, имеют локальную область видимости. Другими словами, эти параметры и переменные используются только внутри функции, в которой они объявлены. Локальные переменные создаются в точке объявления и уничтожаются, когда выходят из области видимости.

Рассмотрим следующую программу:

Параметры a и b функции add() создаются при вызове этой функции, используются только внутри нее и уничтожаются по завершении выполнения этой функции.

Переменные x и y функции main() можно использовать только внутри main() и они также уничтожаются по завершении выполнения функции main().

Для лучшего понимания давайте детально разберем ход выполнения этой программы:

   выполнение начинается с функции main();

   создается переменная x в функции main() и ей присваивается значение 7;

   создается переменная y в функции main() и ей присваивается значение 8;

   вызывается функция аdd() с параметрами 7 и 8;

   создается переменная a в функции add() и ей присваивается значение 7;

   создается переменная b в функции add() и ей присваивается значение 8;

   выполняется операция сложения чисел 7 и 8, результатом является значение 15;

   функция add() возвращает значение 15 обратно в caller (в функцию main());

   переменные a и b функции add() уничтожаются;

   функция main() выводит значение 15 на экран;

   функция main() возвращает 0 в операционную систему;

   переменные x и y функции main() уничтожаются.

Всё!

Обратите внимание, если бы функция add() вызывалась дважды, параметры a и b создавались и уничтожались бы также дважды. В программе с большим количеством функций, переменные создаются и уничтожаются часто.

Локальная область видимости предотвращает возникновение конфликтов имен

Из примера, приведенного выше, понятно, что переменные x и y отличаются от переменных a и b.

Теперь давайте рассмотрим следующую программу:

Здесь мы изменили имена переменных x и y функции main() на a и b. Программа по-прежнему работает корректно, несмотря на то, что функция add() также имеет переменные a и b. Почему это не вызывает конфликта имен? Дело в том, что a и b, принадлежащие функции main(), являются локальными переменными, функция add() не может их видеть, точно так же, как функция main() не может видеть переменные a и b, принадлежащие функции add(). Ни add(), ни main() не знают, что они имеют переменные с одинаковыми именами!

Это значительно снижает возможность возникновения конфликта имен. Любая функция не должна знать или заботиться о том, какие переменные находятся в другой функции. Это также предотвращает возникновение ситуаций, когда одни функции могут непреднамеренно (или намеренно) изменять значения переменных других функций.

Правило: Имена, которые используются внутри функции (включая параметры), доступны/видны только внутри этой же функции.

Тест


Каким будет результат выполнения следующей программы?

Ответ

Результат выполнения программы:

main: a = 6 and b = 7
doMath: a = 6 and b = 5
doMath: a = 4 and b = 5
main: a = 6 and b = 7

Вот ход выполнения этой программы:

   выполнение начинается с функции main();

   создается переменная a в функции main(), ей присваивается значение 6;

   создается переменная b в функции main(), ей присваивается значение 7;

   cout выводит main: a = 6 and b = 7;

   вызывается doMath() с аргументом 6;

   создается переменная a в функции doMath(), ей присваивается значение 6;

   выполняется инициализация переменной b функции doMath() значением 5;

   cout выводит doMath: a = 6 and b = 5;

   переменной a функции doMath() присваивается значение 4;

   cout выводит doMath: a = 4 and b = 5;

   переменные a и b функции doMath() уничтожаются;

   cout выводит main: a = 6 and b = 7;

   функция main() возвращает 0 в операционную систему;

   переменные a и b функции main() уничтожаются.

Обратите внимание, даже когда мы присвоили значения переменным a и b внутри функции doMath(), на переменные внутри функции main() это никак не повлияло.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (1 108 оценок, среднее: 4,90 из 5)
Загрузка...

Комментариев: 20

  1. Игорь:

    Здравствуйте. Перечитал урок про тип возвратных функций и не понял всё равно. Если тип функции void не возвращает значения в caller, то как в этом случае функция с типом void выводит на экран значения?

    1. Фото аватара Юрий:

      Функция типа void может выводить данные на экран через стеймтенты cout — для этого ей ничего не нужно возвращать в caller.

  2. Анастасия:

    Здраствуйте! Что такое caller, ранее несколько раз перечитывала уроки, но так и не поняла, можно примеры кода и из жизни. Благодарю!

    1. Фото аватара Юрий:

      caller — это функция, которая вызывает другую функцию. В уроке №12 об этом говорится — https://ravesli.com/urok-12-funktsii-i-return/#toc-0

  3. Андрей:

    Здравствуйте.
    Материал отличны, легко и интересно читать.
    Спасибо

    Относительно последнего теста в уроке №15
    Исходя из правила: "Имена, которые используются внутри функции (включая параметры), доступны/видны только внутри этой же функции."

    Исходя из правила немного не понятно как и откуда переменная "а" получает значение "6". По моему пониманию значение все таки взято из  main так называемого caller и передано в функцию doMath и присвоено опять же переменной "a". ведь в функции doMath до исполнения строки кода std::cout << "doMath: a = " << a << " and b = " << b << std::endl; значение переменной "а" определено не было.

    Но вот что меня совсем запутало так это то что все происходит и самое главное компилируется без ошибок — так это то что функция doMath с типом возврата void.

    Поясните пожалуйста для тех кто в танке.
    Заранее благодарен.

    1. aaa:

      компилятор все выполняет построчно. научись читать его построчно будет легче учить.
      так вот:
      16: компилятор обращается к строке 3 с параметром а=6. так как в мейн видит только свою переменную а. в функции doMath создается своя локальная переменная а значение которой взято из мейн.

      7: переменной а присваивается значение из 6 на 4. переменной а из мейн в этом блоке не существует.

      может тебя запутало что они одинаково называются.
      могло быть вот так

      функция doMath ничего не возвращает. она просто выводит на экран и сразу закрывается(ничего не нужно хранить в памяти чисто инструкции). а переменной a и b в функции doMath выделяется место в памяти и потом сразу удаляется

      1. Андрей:

        Спасибо за развернутый ответ. Как только отправил вопрос сразу понял что "функция doMath ничего не возвращает. она просто выводит на экран и сразу закрывается"

  4. Михаил:

    не понял как формируются две срединных строки. Почему сначала аргументу "a" сначала присваивается значение из main-на, а потом из doMath ? А "b" всегда остается из doMath ?

    1. Сергей:

      В ответе написан ход выполнения программы. Перечитайте его

  5. Андрей:

    Можете объяснить, что означает выход из области видимости(какой нибудь жизненный пример привести), и как переменные после этого уничтожаются.
    Я хоть и внимательно прочитал и законспектировал, но эти 2 момента не понял

    1. Константин:

      Андрей, ну вот представь подсобные хозяйства на селе: фигурные скобки в функции это ограничители вольера (область видимости), животные это переменные, килограммы массы — их значения. Какие имена хрюшек? Правильно! Внутри одной области видимости уникальные, а вне — одинаковые. Пусть дело происходит в мультфильме. Тогда мы можем взять килограммы одной хрюшки и не отобрать их у неё, а именно скопировать в другую хрюшку при этом вытеснив уже имевшиеся кг в последней! Андэсденд ми?

      1. Андрей:

        Спасибо за ответ.
        Про область видимости я давно понял, а про уничтожение переменных не до конца понимал.
        Я тут у прогеров поспрашивал и они сказали, что уничтожение — вынос мусора из памяти. И тогда да меня дошло

  6. данила:

    судя из теста понятно так же что уничтожаются аргументы ,сами то параметры остаются. Но аргумент так же уничтожается после объявления нового аргумента к этому же параметру . Как пример ,в функции майн() переопределил значение переменной B ( В=8),получается что предыдущее значение В (7) уничтожено. Так ли я понял урок?

    1. Данила:

      По-сути в памяти мы берем ячейку и помещаем туда значение инициализированной переменной, а потом уже кладем в эту ячейку, то бишь изменяем значение переменной, различные значения. Получается, что переменная b создается один раз и уничтожается один раз, когда выходим из области видимости main.

  7. Александра:

    Отличный урок! Да и все остальные тоже =) Понятным и доступным языком все объясняется.
    Но вот проблема с этим уроком: не посмотреть ответ на тест =(

  8. Степан:

    Привет! Будешь дальше переводить оригинальный сайт?
    Интересно почитать про жесть из STL.

    Отличный сайтец, спасибо!

    1. Фото аватара Юрий:

      Привет. Да, малость уроков осталась. Самому тоже интересно дойти до STL.

      Пожалуйста 🙂

  9. painkiller:

    Очень полезный урок. Спасибо!

    1. Фото аватара Юрий:

      Пожалуйста 🙂

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *