Як ми вже знаємо з попередніх уроків, при виконанні процесором стейтменту int х;
створюється змінна. Виникає питання: «Коли ця змінна знищується?”.
Область видимості змінної визначає, хто може бачити і використовувати змінну під час її існування. І параметри функції, і змінні, які оголошені всередині функції, мають локальну область видимості. Іншими словами, ці змінні використовуються тільки всередині функції, в якій вони оголошені. Локальні змінні створюються в точці оголошення і знищуються, коли виходять із області видимості.
Розглянемо наступну програму:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <iostream> int add(int a, int b) // тут створюються змінні a і b { // a і b можна побачити/використати тільки всередині цієї функції return a + b; } // тут a і b виходять із області видимості int main() { int x = 7; // тут створюється і ініціалізується змінна x int y = 8; // тут створюється і ініціалізується змінна y // x і y можна використовувати тільки всередині функції main() std::cout << add(x, y) << std::endl; // виклик функції add() з a = x і b = y return 0; } // тут x і y виходять із області видимості і знищуються |
Параметри 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
назад у викликаючу функцію (в функцію main());
змінні функції add() a
і b
знищуються;
функція main() виводить значення 15
на екран;
функція main() повертає 0
в операційну систему;
змінні x
і y
функції main() знищуються.
Все!
Зверніть увагу, якби функція add() викликалася двічі, то параметри a
і b
створювалися і знищувалися б також двічі. У програмі з великою кількістю функцій, змінні часто створюються і знищуються.
Локальна область видимості запобігає виникненню конфліктів імен
З вищенаведеного прикладу зрозуміло, що змінні x
і y
відрізняються від змінних a
і b
. Тепер давайте розглянемо наступну програму:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <iostream> int add(int a, int b) // тут створюються змінні a і b функції add() { return a + b; } // тут a і b функції add() виходять із області видимості і знищуються int main() { int a = 7; // тут створюється змінна a функції main() int b = 8; // тут створюється змінна b функції main() std::cout << add(a, b) << std::endl; // значення змінних a і b функції main() копіюються в змінні a і b функції add() return 0; } // тут a і b функції main() виходять із області видимості і знищуються |
Тут ми змінили імена змінних x
і y
функції main() на a
і b
. Програма, як і раніше працює коректно, не дивлячись на те, що функція add() також має змінні a
і b
. Чому це не викликає конфлікт імен? Справа в тому, що a
і b
функції main() є локальними змінними, функція add() не може їх бачити (і навпаки). Ні add(), ні main() не знають, що вони мають змінні з однаковими іменами!
Це значно знижує можливість виникнення конфлікту імен. Будь-яка функція не повинна знати або турбуватися про те, які змінні знаходяться в іншій функції. Це також запобігає виникненню ситуацій, коли одні функції можуть ненавмисно (або навмисно) змінювати значення змінних інших функцій.
Правило: Ідентифікатори, які використовуються всередині функції (включаючи параметри), доступні тільки всередині цієї ж функції.
Тест
Який результат виконання наступної програми?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <iostream> void doMath(int a) { int b = 5; std::cout << "doMath: a = " << a << " and b = " << b << std::endl; a = 4; std::cout << "doMath: a = " << a << " and b = " << b << std::endl; } int main() { int a = 6; int b = 7; std::cout << "main: a = " << a << " and b = " << b << std::endl; doMath(a); std::cout << "main: a = " << a << " and b = " << b << std::endl; return 0; } |
Відповідь
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
;
std::cout виводить на екран main: a = 6 and b = 7
;
викликається функція doMath() з аргументом 6
;
створюється змінна a
функції doMath() і їй присвоюється значення 6
;
виконується ініціалізація змінної b
функції doMath() значенням 5
;
std::cout виводить на екран doMath: a = 6 and b = 5
;
змінній a
функції doMath() присвоюється значення 4
;
std::cout виводить на екран doMath: a = 4 and b = 5
;
a
і b
функції doMath() знищуються;
std::cout виводить на екран main: a = 6 and b = 7
;
функція main() повертає 0
в операційну систему;
змінні a
і b
функції main() знищуються.
Зверніть увагу, навіть коли ми присвоювали значення змінним a
і b
всередині функції doMath(), на змінні всередині функції main() це ніяк не вплинуло.