Як ми вже знаємо з попередніх уроків, при виконанні процесором стейтменту 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() це ніяк не вплинуло.
