Урок №52. Глобальні змінні

  Юрій  | 

  Оновл. 10 Тра 2020  | 

 95

Ми вже знаємо, що змінні, оголошені всередині блоку, називаються локальними. Вони мають локальну область видимості (використовуються тільки всередині блоку, в якому оголошені) і автоматичну тривалість (створюються в точці визначення і знищуються в кінці блоку).

Глобальними називаються змінні, які оголошені поза блоком. Вони мають статичну тривалість, тобто створюються при запуску програми і знищуються при її завершенні. Глобальні змінні мають глобальну область видимості (або ще “файлову область видимості“), тобто їх можна використовувати в будь-якому місці файлу, в якому вони оголошені.

Визначення глобальних змінних

Зазвичай глобальні змінні оголошують у верхній частині коду, нижче директив #include, але вище будь-якого іншого коду, наприклад:

Подібно до того, як змінні у внутрішньому блоці приховують змінні з тими ж іменами в зовнішньому блоці, локальні змінні приховують глобальні змінні з однаковими іменами всередині блоку, в якому вони визначені. Однак, за допомогою оператора дозволу області видимості (::), компілятору можна повідомити, яку версію змінної ви хочете використовувати: глобальну чи локальну. Наприклад:

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

Global value: 3
Local value: 9

Використовувати однакові імена для локальних і глобальних змінних — це прямий шлях до проблем і помилок, тому подібне робити не рекомендується. Багато розробників додають до глобальних змінних префікс g_ (“g” від англ. “global”). Таким чином можна вбити відразу двох зайців: визначити глобальні змінні і уникнути конфліктів імен з локальними змінними.

Ключові слова static і extern

В якості доповнення до області видимості і тривалості, змінні мають ще одну властивість: зв’язок. Зв’язок змінної визначає, чи належать декілька згадок одного ідентифікатора до однієї і тієї ж змінної чи ні.

Змінна без зв’язків — це змінна з локальною областю видимості, яка відноситься тільки до блоку, в якому вона визначена. Це звичайні локальні змінні. Дві змінні з однаковими іменами, але визначені в різних функціях, не мають ніякого зв’язку — кожна з них вважається незалежною бойовою одиницею.

Змінна, що має внутрішні зв’язки, називається внутрішньою змінною (або ще “статичною змінною“). Вона може використовуватися в будь-якому місці файлу, в якому визначена, але не відноситься до чого-небудь поза цього файлу.

Змінна, що має зовнішні зв’язки, називається зовнішньою змінною. Вона може використовуватися як в файлі, в якому визначена, так і в інших файлах.

Якщо ви хочете зробити глобальну змінну внутрішньою (яку можна використовувати тільки всередині одного файлу) — використовуйте ключове слово static:

Аналогічно, якщо ви хочете зробити глобальну змінну зовнішньою (яку можна використовувати в будь-якому файлі програми) — використовуйте ключове слово extern:

За замовчуванням, неконстантні змінні, оголошені поза блоком, вважаються зовнішніми. Однак константні змінні, оголошені поза блоком, вважаються внутрішніми.

Попередні оголошення змінних з використанням extern

З уроку №23 ми вже знаємо, що для використання функцій, які визначені в іншому файлі, потрібно використовувати попередні оголошення.

Аналогічно, щоб використовувати зовнішню глобальну змінну, яка була оголошена в іншому файлі, потрібно записати попереднє оголошення змінної з використанням ключового слова extern (без значення для ініціалізації). Наприклад:

global.cpp:

main.cpp:

Якщо попереднє оголошення знаходиться поза блоком, то воно застосовується до всього файлу. Якщо ж всередині блоку, то воно застосовується тільки до нього.

Якщо змінна оголошена за допомогою ключового слова static, то отримати доступ до неї за допомогою попереднього оголошення не вийде, наприклад:

constants.cpp:

main.cpp:

Зверніть увагу, якщо ви хочете визначити неініціалізовану неконстантну глобальну змінну, то не використовуйте ключове слово extern, інакше C++ буде думати, що ви намагаєтеся записати попереднє оголошення.

Зв’язки функцій

Функції мають такі ж властивості зв’язку, що і змінні. За замовчуванням вони мають зовнішній зв’язок, який можна змінити на внутрішній за допомогою ключового слова static:

Попередні оголошення функцій не потребують ключового слова extern. Компілятор може визначити сам (по тілу функції): визначаєте ви функцію чи пишете її прототип.

Файлова область видимості vs. Глобальна область видимості

Терміни “файлова область видимості” і “глобальна область видимості”, як правило, викликають подив, і це частково пояснюється їх неофіційним використанням. У теорії, в C++ всі глобальні змінні мають файлову область видимості. Однак по факту, термін “файлова область видимості” частіше застосовується до внутрішніх глобальних змінних, а “глобальна область видимості” до зовнішніх глобальних змінних.

Наприклад, розглянемо наступну програму:

global.cpp:

main.cpp:

g_y має файлову область видимості всередині global.cpp. Доступ до цієї змінної поза файлом global.cpp — заборонений. Зверніть увагу, хоч ця змінна і використовується в main.cpp, сам main.cpp не бачить її, він бачить тільки попереднє оголошення g_y (яке також має файлову область видимості). Лінкер відповідає за зв’язування визначення g_y в global.cpp з використанням g_y в main.cpp.

Глобальні символьні константи

В уроці про символьні константи, ми визначали їх наступним чином:

constants.h:

Хоч це просто і відмінно підходить для невеликих програм, але кожен раз, коли constants.h підключається в інший файл, кожна з цих змінних копіюється в цей файл. Таким чином, якщо constants.h підключити в 20 різних файлів, то кожна з змінних продублюється 20 разів. Header guards не зупинять це, так як вони тільки запобігають підключенню заголовку більш ніж один раз в один файл. Дублювання змінних насправді не є проблемою (оскільки константи часто не займають багато пам’яті), але зміна значення однієї константи потребує перекомпіляції кожного файлу, в якому вона використовується, що може привести до великих тимчасових витратах в великих проектах.

Уникнути цієї проблеми можна, перетворивши ці константи в константні глобальні змінні, і змінивши заголовки тільки для зберігання попередніх оголошень змінних. Наприклад:

constants.cpp:

constants.h:

Їх використання в коді залишається незмінним:

Тепер визначення символьних констант виконується тільки один раз (в constants.cpp). Будь-які зміни, зроблені в constants.cpp, потребують перекомпіляції тільки (одного) цього файлу.

Але є і зворотна сторона медалі: такі константи більше не будуть вважатися константами часу компіляції і, тому, не зможуть використовуватися будь-де, де буде потрібна константа такого типу.

Оскільки глобальні символьні константи повинні знаходитися в окремому просторі імен і бути доступними тільки для читання, то використовувати префікс g_ — вже не обов’язково.

Попередження про (неконстантні) глобальні змінні

У початківців часто виникає спокуса використовувати просто безліч глобальних змінних, оскільки з ними легко працювати, особливо коли задіяно багато функцій. Проте, цього слід уникати! Чому? Про це ми поговоримо в наступному уроці.

Висновки

Підсумуємо вищесказане:

   Глобальні змінні мають глобальну область видимості і можуть використовуватися в будь-якому місці програми. Подібно до функцій, ви повинні використовувати попередні оголошення (з ключовим словом extern), щоб використовувати глобальну змінну, визначену в іншому файлі.

   За замовчуванням, глобальні неконстантні змінні мають зовнішній зв’язок. Ви можете використовувати ключове слово static, щоб зробити їх внутрішніми.

   За замовчуванням, глобальні константні змінні мають внутрішній зв’язок. Ви можете використовувати ключове слово extern, щоб зробити їх зовнішніми.

   Використовуйте префікс g_ для ідентифікації ваших неконстантних глобальних змінних.

Ось приклади використання ключових слів extern і static з неконстантними і константними змінними:

Тест

У чому різниця між областю видимості, тривалістю і зв’язком змінних? Які типи тривалості, області видимості і зв’язку мають глобальні змінні?

Відповідь

   Область видимості визначає, де змінна доступна для використання. Тривалість визначає, де змінна створюється/знищується. Зв’язок визначає, чи може змінна використовуватися в іншому файлі чи ні.

   Глобальні змінні мають глобальну область видимості (або ще “файлову область видимості”), що означає, що вони доступні з точки оголошення до кінця файлу, в якому оголошені.

   Глобальні змінні мають статичну тривалість, що означає, що вони створюються при запуску програми і знищуються при її завершенні.

   Глобальні змінні можуть мати або внутрішній, або зовнішній зв’язок (що можна змінити через використання ключових слів static і extern).

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (2 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

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