Область видимости переменной в C++

User Rating: 5 / 5

С точки зрения программы C++ под областью видимости понимают определённый регион или участок программы, где переменная видима (от этого и название "область видимости"), т.е. к ней можно в этом регионе/участке обращаться, получая её значение. Переменная в языке C++ может быть определена в одном из следующих регионов/участков программы, а попросту говоря, мест:

  • вне всех функций программы. В этом случае говорят, что это глобальная область видимости переменной (global scope), а саму переменную называют также глобальной. Глобальная переменная видна во всех методах и блоках программы.
  • внутри функции или блока. В этом случае говорят, что переменная объявлена с локальной областью видимости (local scope). Саму переменную при этом называют также локальной. Локальная переменная видна в том локальном блоке, где объявлена, и во всех вложенных  по отношению к нему блоках. Если она объявлена в начале тела функции, то она видна и во всех внутренних блоках этой функции (при условии, что её не перекрывает другое определение переменной с таким же именем).
  • внутри определения параметров функции. В этом случае говорят о том, что переменная является формальным параметром функции. Формальный параметр функции виден на всём участке тела функции, т.е. во всех блоках этой функции.

Глобальные переменные

Давайте посмотрим на пример определения глобальной переменной в C++. Как следует из описания выше, она должна располагаться вне всех функций программы. На практике это выглядит очень просто: для определения глобальной переменной мы в буквальном смысле "выносим" её определение за пределы всех существующих функций программы. Ниже показана глобальная переменная целого типа с именем my_global_var:

#include <iostream>

using namespace std;

int my_global_var = 100;

int main() {
    cout << "Demo of global variable" << endl;
    cout << "my_global_var = " << my_global_var << endl;
}

int get_value_multiply_10(int x) {
    return x * 10;
}

Ну, и как видим, определение переменной my_global_var полностью соответствует вышесказанному: она определена вне функции main(), которая является входной точкой нашей программы, а также определена вне функции get_value_multiply_10(int x).

При запуске нашей программы она выведет на экран приветственный заголовок и значение нашей глобальной переменной:

Demo of global variable:
my_global_var = 100

Ровно таким же образом может определяться переменная любого другого типа, а не только int, как показано в примере выше.

Глобальные переменные видны из любой функции программы. Они сохраняют своё значение в течение всего времени работы программы.

Локальные переменные

В отличие от глобальных, локальные переменные, как опять же следует из их названия, определяются локально, т.е. внутри функции или блока. Что ж, давайте посмотрим, что это означает на примере:

#include <iostream>

using namespace std;

int my_global_var = 100;

int main() {
    int x = 2, y = 10, z = 50;

    cout << "Demo of global variable:" << endl;
    cout << "my_global_var = " << my_global_var << endl;

    cout << "Demo of local variables:" << endl;
    cout << "x = " << x << ", y = " << y << ", z = " << z << endl;
}

int get_value_multiply_10(int x) {
    return x * 10;
}

Как видно из листинга программы выше, мы объявили три локальных переменных внутри метода main(): x, y и z и инициализировали их значениями 2, 10 и 50, соответственно. Запуск программы покажет нам следующий результат:

Demo of global variable:
my_global_var = 100
Demo of local variables:
x = 2, y = 10, z = 50

Также локальная переменная может определяться на одном из уровней блоков, входящих в тело метода. Например, таким блоком может являться оператор if-else:

using namespace std;

int my_global_var = 100;

int main() {
    int x = 2, y = 10, z = 50;

    cout << "Demo of global variable:" << endl;
    cout << "my_global_var = " << my_global_var << endl;

    cout << "Demo of local variables:" << endl;
    cout << "x = " << x << ", y = " << y << ", z = " << z << endl;

    if (x > 0) {
        int t = x; // t - это локальная переменная внутри блока if
        cout << "t = " << t << endl;
        int y = 2000; // y - ещё одна локальная переменная внутри блока if, "перекрывает" y, заданную в main()
        cout << "y = " << y << endl;
    }
    else {
        int h = -x; // h - ещё одна локальная переменная внутри блока else
        cout << "h = " << h << endl;
        int x = 1000; // x - ещё одна локальная переменная внутри блока else, "перекрывает" x, заданную в main()
        cout << "x = " << x << endl;
    }
}

int get_value_multiply_10(int x) {
    return x * 10;
}

Посмотрим на отличия: у нас добавился блок if-else, в каждой ветке которого определяются переменные t и h, которые также являются локальными. Их область видимости - начиная с конкретной ветки if-else, где они определены и "ниже" - т.е. до всех более вложенных блоков, если бы они определялись внутри if или else. Также обратите внимание, что мы задаем ещё одни локальные переменные x и y, которые "перекрывают" переменные, заданные сразу после main() с такими же именами.

После запуска программы отобразится следующее (ожидаемо, значение y сначала выводится равным 10, а затем 2000, поскольку второй раз он выводится из той переменной y, что задана в блоке if):

Demo of global variable:
my_global_var = 100
Demo of local variables:
x = 2, y = 10, z = 50
t = 2
y = 2000

Локальные переменные перестают быть видимыми, как только завершается блок, в котором они были объявлены. Если локальная переменная объявлена внутри функции, то она будет сразу недоступна по выходу из этой функции. Аналогично, если локальная переменная объявлена в каком-то внутреннем блоке функции (например, в операторе if-else), то она сразу перестанет существовать по выходу из этого  внутреннего блока.

Формальные параметры функций

Здесь всё очень просто: под формальными параметрами функций понимаются те переменные, которые являются входными параметрами функции. Например, в примерах выше таким параметром является переменная x с типом int, которая входит в список параметров функции get_value_multiply_10(int x):

int get_value_multiply_10(int x) {
    return x * 10;
}

Формальный параметр будет виден также и во всех внутренних блоках функции. Давайте покажем это на примере, добавив в тело нашей функции простой оператор if-else:

int get_value_multiply_10(int x) {
    if (x > 0) {
        return x * 10;
    } else {
        return x * -10;
    }
}

С добавленным блоком if-else функция теперь всегда будет возвращать неотрицательное число. Видим, что наш формальный параметр функции с именем x доступен и внутри if-else.

Инициализация глобальных и локальных переменных

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

Глобальные переменные, в отличие от локальных, могут получить значение по умолчанию, даже если Вы не инициализируете их.

Ниже представлены значения по умолчанию для глобальных переменных различных типов данных:

  • для глобальной переменной типа int значение по умолчанию 0
  • для глобальной переменной типа char значение по умолчанию '\0'
  • для глобальной переменной типа float значение по умолчанию 0
  • для глобальной переменной типа double значение по умолчанию 0
  • для глобальной переменной типа bool значение по умолчанию false (0)
  • для глобальной переменной типа указатель (об указателях речь пойдет в других статьях, когда мы до них доберёмся) значение по умолчанию NULL

Хорошей практикой программирования является своевременная инициализация локальных переменных, поскольку если Вы этого не делаете, то программа может вести себя непредсказуемо! Это может быть причиной трудноуловимых дефектов программы, на поиск причины которых Вы потом потратите уйму времени. Поэтому приучите себя сразу инициализировать локальные переменные (а желательно и глобальные тоже) каким-то конкретным значением.

Всем удачи в использовании глобальных и локальных переменных в Ваших программах, делитесь в комментариях своими отзывами, мыслями, впечатлениями.

Яндекс.Метрика