Урок №52. Связи, область видимости и продолжительность жизни переменных

  Юрий  | 

  |

  Обновл. 20 Фев 2023  | 

 56571

 ǀ   11 

Мы уже ранее рассматривали, что такое область видимости, продолжительность жизни, связи и то, какими они могут быть в языке С++. Давайте сейчас закрепим это всё.

Область видимости

Область видимости идентификатора определяет, где он доступен для использования. К идентификатору, который находится вне области видимости, доступ закрыт.

   Переменные с локальной/блочной областью видимости доступны только в пределах блока, в котором они объявлены. Это:

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

   параметры функции.

   Переменные с глобальной/файловой областью видимости доступны в любом месте программы/файла. Это:

   глобальные переменные.

Продолжительность жизни


Продолжительность жизни переменной определяет, где она создается и где уничтожается.

   Переменные с автоматической продолжительностью жизни создаются в точке определения и уничтожаются при выходе из блока, в котором определены. Это:

   обычные локальные переменные.

   Переменные со статической продолжительностью жизни создаются, когда программа запускается, и уничтожаются при её завершении. Это:

   глобальные переменные;

   статические локальные переменные.

   Переменные с динамической продолжительностью жизни создаются и уничтожаются по запросу программиста. Это:

   динамические переменные (о них мы поговорим на соответствующем уроке).

Связи

Связь идентификатора определяет, относятся ли несколько упоминаний одного идентификатора к одному и тому же идентификатору или нет.

   Идентификаторы без связей — это идентификаторы, которые ссылаются сами на себя. Это:

   обычные локальные переменные;

   пользовательские типы данных, такие как enum, typedef и классы, объявленные внутри блока (об этом детально поговорим на соответствующих уроках).

   Идентификаторы с внутренней связью доступны в любом месте файла, в котором они объявлены. Это:

   статические глобальные переменные (инициализированные или неинициализированные);

   константные глобальные переменные;

   статические функции (о них поговорим чуть позже).

   Идентификаторы с внешней связью доступны как в любом месте файла, в котором они объявлены, так и в других файлах (через предварительное объявление). Это:

   обычные функции;

   неконстантные глобальные переменные (инициализированные или неинициализированные);

   внешние константные глобальные переменные;

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

Идентификаторы с внешней связью могут вызвать ошибку дублирования определений, если определения скомпилированы в более чем одном файле .cpp.

Функции по умолчанию имеют внешнюю связь, что можно изменить с помощью ключевого слова static (на внутреннюю связь).

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

Резюмируем


Весь материал, изложенный выше:

Тип Пример Область видимости Продолжительность жизни Связь Примечание
Локальная переменная int x; Локальная область видимости Автоматическая продолжительность жизни Нет связей
Статическая локальная переменная static int s_x; Локальная область видимости Статическая продолжительность жизни Нет связей
Динамическая переменная int *x = new int; Локальная область видимости Динамическая продолжительность жизни Нет связей
Параметр функции void foo(int x) Локальная область видимости Автоматическая продолжительность жизни Нет связей
Внешняя неконстантная глобальная переменная int g_x; Глобальная область видимости Статическая продолжительность жизни Внешняя связь Инициализированная или неинициализированная.
Внутренняя неконстантная глобальная переменная static int g_x; Глобальная область видимости Статическая продолжительность жизни Внутренняя связь Инициализированная или неинициализированная.
Внутренняя константная глобальная переменная const int g_x(1); Глобальная область видимости Статическая продолжительность жизни Внутренняя связь Должна быть инициализирована.
Внешняя константная глобальная переменная extern const int g_x(1); Глобальная область видимости Статическая продолжительность жизни Внешняя связь Должна быть инициализирована.

Предварительные объявления

С помощью предварительного объявления мы можем получить доступ к функции или переменной из другого файла:

Тип Пример Примечание
Предварительное объявление функции void foo(int x); Только прототип, без тела функции.
Предварительное объявление неконстантной глобальной переменной extern int g_x; Переменная НЕ должна быть инициализирована.
Предварительное объявление константной глобальной переменной extern const int g_x; Переменная НЕ должна быть инициализирована.

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

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

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

  1. Владимир:

    Почему-то возникает ошибка при компиляции файлов «undefined reference to `g_x1′». Можете подсказать, что я не так сделал? Как я понял, компилятор не связывает объявление «extern const int g_x1» и инициализацию в другом файле «const int g_x1 = 5». Но как это исправить?

    1. kamawui:

      При объявлении глобальной константы g_x1 на четвертой строке второго файла не было использовано ключевое слово extern. Константа доступна только файлу, в котором была объявлена

  2. Денис:

    Спасибо большое за этот материал.

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

      Пожалуйста)

  3. MR:

    Огромное СПАСИБОООО!!!!!

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

      Пожалуйста 🙂

  4. Михаил:

    Внешняя неконстантная глобальная переменная может быть не инициализированной. Тогда вопрос, как компилятор понимает, что это определение переменной, а не предварительное объявление переменной определенной где-то во внешнем файле.
    Например имеем код в начале файла:

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

    1. Влад:

      Ключевое слово extern, при ОПРЕДЕЛЕНИИ неконстантной глобальной переменной int g_y, в каком-нибудь внешнем файле, писать НЕ нужно. Как раз-таки когда мы хотим сделать ПРЕДВАРИТЕЛЬНОЕ ОБЪЯВЛЕНИЕ то пишем ключевое слово extern (мы как бы указываем компилятору с помощью слова extern что переменную g_y нужно использовать из другого файла)

  5. Владимир:

    Кажется это самый серьезный головняк из пройденного. Разнообразие, подобие и отличие всех этих вариантов переменных реальный треш. Вроде не сложно, но запомнить это — просто нечто…

    1. winnie:

      Да, последние несколько тем — выносят мозг. Это все, конечно, нужно знать, но, имхо, только многократное применение на практике может помочь это все запомнить и корректно использовать… Я эти темы даже не стараюсь зазубрить и полностью понять, пока просто читаю для общего развития 🙂

    2. Артемий:

      Надо читать по настроению, не заучивать… Сложно, но понятно все.

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

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