Урок №105. Передача по адресу

  Юрій  | 

  Оновл. 18 Січ 2021  | 

 27

Є ще один спосіб передачі змінних у функцію в мові C++ — по адресу.

Передача по адресу

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

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

value = 4
value = 7

Як ви можете бачити, функція boo() змінила значення аргументу (змінну value) через параметр-вказівник ptr. Передачу по адресу зазвичай використовують з вказівниками на звичайні масиви. Наприклад, наступна функція виведе всі значення масиву:

Ось приклад програми, яка викликає цю функцію:

Результат:

9 8 6 4 3 2 1

Пам’ятайте, що фіксовані масиви конвертуються у вказівники при передачі у функцію, тому їх довжину потрібно передавати в якості окремого параметру. Перед розіменуванням параметрів, переданих по адресу, не зайвим буде перевірити — чи не є вони нульовими вказівниками. Розіменування нульового вказівника призведе до збою в програмі. Ось функція printArray() з перевіркою (виявленням) нульових вказівників:

Передача по константному адресу

Оскільки printArray() все одно не змінює значення отриманих аргументів, то гарною ідеєю буде зробити параметр array константою:

Так ми бачимо відразу, що printArray() не змінить переданий аргумент array. Коли ви передаєте вказівник у функцію по адресу, то значення цього вказівника (адреса, на яку він вказує) копіюється з аргументу в параметр функції. Іншими словами, він передається по значенню! Якщо змінити значення параметру функції, то зміниться тільки копія, вихідний вказівник-аргумент не буде змінений. Наприклад:

У tempPtr копіюється адреса вказівника ptr. Незважаючи на те, що ми змінили tempPtr на нульовий вказівник (присвоїли йому nullptr), це ніяк не вплинуло на значення, на яке вказує ptr. Отже, результат виконання програми:

6
6

Зверніть увагу, хоча сама адреса передається по значенню, ви все одно можете розіменувати її для зміни значення вихідного аргументу. Заплутано? Давайте розберемося детально:

   При передачі аргументу по адресу в змінну-параметр функції копіюється адреса з аргументу. У цей момент параметр функції і аргумент вказують на одне і те ж значення.

   Якщо параметр функції потім розіменувати для зміни початкового значення, то це призведе до зміни значення, на яке вказує аргумент, оскільки параметр функції і аргумент вказують на одне і те ж значення!

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

У наступній програмі це все добре проілюстровано:

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

6
7

Передача адресів по посиланню

Виникає питання: «А що, якщо ми хочемо змінити адресу, на яку вказує аргумент, всередині функції?». Виявляється, це можна зробити дуже легко. Ви можете просто передати адресу по посиланню. Синтаксис посилання на вказівник може здатися трохи дивним, але все ж:

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

6 ptr is null

Нарешті, наша функція setToNull() дійсно змінила значення ptr з &six на nullptr!

Існує тільки передача по значенню

Тепер, коли ви розумієте основні відмінності між передачею по посиланню, по адресу і по значенню, давайте трохи поговоримо про те, що знаходиться “під капотом”.

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

Плюси і мінуси передачі по адресу

Плюси передачі по адресу:

   Передача по адресу дозволяє функції змінити значення аргументу, що іноді корисно. В іншому випадку, використовуємо const для гарантії того, що функція не змінить аргумент.

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

   Ми можемо повернути відразу декілька значень з функції, використовуючи параметри виводу.

Мінуси передачі по адресу:

   Всі вказівники потрібно перевіряти, чи не є вони нульовими. Спроба розіменувати нульовий вказівник призведе до збою в програмі.

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

Коли використовувати передачу по адресу:

   при передачі звичайних масивів (якщо немає ніяких проблем з тим, що масиви конвертуються у вказівники при передачі).

Коли не використовувати передачу по адресу:

   при передачі структур або класів (використовуйте передачу по посиланню);

   при передачі фундаментальних типів даних (використовуйте передачу по значенню).

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

Правило: Використовуйте передачу по посиланню, замість передачі по адресу, коли це можливо.

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

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

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

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