Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

8.2. Посилальні параметри

Незважаючи на можливість "вручну" організувати виклик за посиланням за допомогою оператора отримання адреси, такий підхід не завжди є зручним. По-перше, він вимушує програміста виконувати всі операції з використанням покажчиків. По-друге, викликаючи функцію, програміст повинен не забути передати їй адреси аргументів, а не їхнє значення. На щастя, у мові програмування C++ можна зорієнтувати компілятор на автоматичне використання виклику за посиланням (замість виклику за значенням) для одного або декількох параметрів конкретної функції. Така можливість реалізується за допомогою посилального параметра (reference parameter). Під час використання посилального параметра функції автоматично передається адреса (а не значення) аргументу. У процесі виконання коду функції, а саме у процесі вико­нан­ня операцій над посилальним параметром, забезпечується його автоматичне перейменування, і тому програмісту не потрібно використовувати оператори, що працюють з покажчиками.

Посилальний параметр автоматично отримує адресу відповідного аргументу.

Посилальний параметр оголошується за допомогою символу "&", який повинен передувати імені параметра в оголошенні функції. Операції, що виконуються над посилальним параметром, роблять вплив на аргумент, що використовується під час виклику функції, а не на сам посилальний параметр.

8.2.1. Механізм дії посилальних параметрів

Щоб краще зрозуміти механізм дії посилальних параметрів, розглянемо спершу простий приклад. У наведеному нижче коді програми функція fun() приймає один посилальний параметр типу int.

Код програми 8.3. Демонстрація механізму дії посилального параметра

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

void fun(int &izm);

int main()

{

int num = 1;

cout << "Старе значення змінної num: " << num << "\n";

fun(num); // Передаємо адресу змінної num функції fun().

cout << "Нове значення змінної num: " << num << "\n";

getch(); return 0;

}

void fun(int &izm)

{

izm = 10; // Модифікування аргументу, що задається

// під час його виклику.

}

У процесі виконання ця програма відображає на екрані такий результат:

Старе значення змінної num: 1

Нове значення змінної num: 10

Зверніть особливу увагу на визначення функції fun():

void fun(int &izm)

{

izm = 10; // Модифікування аргументу, що задається

// під час його виклику.

}

Отже, розглянемо оголошення параметра izm. Його імені передує символ "&", який "перетворює" змінну izm на посилальний параметр1. Настанова

izm = 10;

(у цьому випадку вона одна утворює тіло функції) не присвоює змінній izm значення 10. Насправді значення 10 присвоюється змінній, на яку посилається змінна izm (у нашій програмі нею є змінна num). Звернемо Вашу увагу на те, що у цій настанові не використовують оператор "*", який є необхідним під час роботи з покажчиками. Застосовуючи посилальний параметр, Ви тим самим повідомляєте С++-компілятор про передачу адреси (тобто покажчика), і компілятор автоматично перейменовує його за Вас. Понад це, якби Ви спробували "допомогти" компіляторові, використавши оператора "*", то відразу ж отримали б повідомлення про помилку (і справді "жодна добра справа не залишається безкарною").

Оскільки змінна izm була оголошена як посилальний параметр, компілятор автоматично передає функції fun() адресу будь-якого аргументу, з яким викликається ця функція. Таким чином, у функції main() настанова

fun(num); // Передаємо адресу змінної num функції fun().

передає функції fun() адресу змінної num (а не її значення). Звернемо Вашу увагу на те, що під час виклику функції fun() не потрібно передувати змінній num оператором "&"1. Оскільки функція fun() отримує адресу змінної num у формі посилання, вона може модифікувати значення цієї змінної.

Щоб проілюструвати реальне застосування посилальних параметрів (і тим самим продемонструвати їх перевагу), перепишемо нашу стару знайому функцію swap() з використанням посилань. У наведеному нижче коді програми зверніть увагу на те, як функція swap() оголошується, а потім викликається.

Код програми 8.4. Демонстрація реального застосування посилальних параметрів

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

// Оголошуємо функцію swap() з використанням посилальних параметрів.

void swap(int &x, int &y);

int main()

{

int izm, jzm;

izm = 10;

jzm = 20;

cout << " Початкові значення змінних izm та jzm: ";

cout << izm << " " << jzm << "\n";

swap(jzm, izm);

cout << " Значення змінних izm та jzm після обміну: ";

cout << izm << " " << jzm << "\n";

getch(); return 0;

}

// Обмін аргументами.

void swap(int &x, int &y)

{

int tmp;

tmp = x; // Зберігаємо значення, розташоване за адресою х.

х = y; // Поміщаємо значення, що зберігається за адресою y

// за адресою х.

y = tmp; // Поміщаємо значення, яке раніше зберігалося

// за адресою х, за адресою y.

}

У цій програмі функція swap() визначається з розрахунку на виклик за посиланням, а не на виклик за значенням. Тому вона може виконати обмін значеннями двох аргументів, з якими вона викликається. Знову ж таки, звернемо Вашу увагу на те, що оголошення х і y посилальними параметрами позбавляє Вас від потреби використання оператора "*" при організації обміну значеннями. Як уже згадувалося вище, така "нав'язливість" з Вашого боку стала б причиною помилки. Тому запам'ятаєте, що компілятор автоматично генерує адреси аргументів, що використовуються під час виклику функції swap(), і автоматично перейменовує посилання x і y.

Отже, підведемо деякі підсумки. Після створення посилальний параметр автоматично посилається (тобто опосередковано вказує) на аргумент, що використовується під час виклику функції. Понад це, під час виклику функції не потрібно застосовувати до аргументу оператор "&". Окрім того, в тілі функції посилальний параметр використовується безпосередньо, тобто без використання оператора "*". Всі операції, що містять посилальний параметр, автоматично виконуються над аргументом, що використовується під час виклику функції.

Необхідно пам'ятати! Привласнюючи певне значення посиланню, Ви насправді присвоюєте це значення змінній, на яку вказує це посилання. Тому, застосовуючи посилання як аргумент функції, під час виклику функції Ви насправді використовуєте таку змінну.