Урок №43. Інкремент, декремент і побічні ефекти

  Юрій  | 

  Оновл. 5 Лип 2020  | 

 293

Операції інкременту (збільшення на 1) і декременту (зменшення на 1) змінних настільки поширені, що у них є свої власні оператори в C++. Плюс ще й дві версії: префікс і постфікс.

Оператор Символ Приклад Операція
Префіксний інкремент (пре-інкремент) ++ ++x Інкремент x, а потім обчислення x
Префіксний декремент (пре-декремент) −− −−x Декремент x, а потім обчислення x
Постфіксний інкремент (пост-інкремент) ++ x++ Обчислення x, а потім інкремент x
Постфіксний декремент (пост-декремент) −− x−− Обчислення x, а потім декремент x

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

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

Розглянемо код вище детальніше. По-перше, компілятор створює тимчасову копію х, яка має те ж значення, що і оригінал (5). Потім збільшується початковий х з 5 до 6. Після цього компілятор повертає тимчасову копію, значенням якої є 5, і присвоює її змінній y. Тільки після цього копія x знищується. Отже, в наведеному вище прикладі, ми отримаємо у = 5 і х = 6.

Ось ще один приклад, який показує різницю між версіями префікс і постфікс:

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

5 5
6 4
6 4
6 4
7 3

У рядку №7 змінні х і у збільшуються/зменшуються на одиницю безпосередньо перед обробкою компілятором, так що відразу виводяться їх нові значення. А в рядку №9 тимчасові копії (х = 6, у = 4) відправляються в cout, а вже тільки потім оригінальні х і у збільшуються/зменшуються на одиницю. Саме тому зміни значень змінних після виконання операторів версії постфікс не видно до наступного рядка.

Версія префікс збільшує/зменшує значення змінних перед обробкою компілятором, версія постфікс — після обробки компілятором.

Правило: Використовуйте префіксний інкремент і префіксний декремент замість постфіксного інкременту і постфіксного декременту. Версії префікс не тільки більш продуктивні, але і помилок з ними (за статистикою) менше.

Побічні ефекти

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

У більшості випадкі побічні ефекти є корисними:

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

Також побічні ефекти можуть приводити і до несподіваних результатів:

C++ не визначає порядок, в якому обчислюються аргументи функції. Якщо лівий аргумент буде обчислюватися першим, то add(5, 6) і результат — 11. Якщо правий аргумент буде обчислюватися першим, то add(6, 6) і результат — 12! А проблема то криється в побічному ефекті одного з аргументів функції add().

Ось ще один приклад:

Який результат виконання цієї програми? Якщо інкремент х виконається до операції присвоювання, то відповідь — 1. Якщо ж після операції присвоювання, то відповідь — 2.

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

Правило: Не використовуйте змінну з побічним ефектом більше одного разу в одному стейтменті.

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

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

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

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