Урок №107. Вбудовані функції

  Юрій  | 

  Оновл. 27 Сер 2021  | 

 222

Використання функцій має багато переваг, в тому числі:

   Код, який знаходиться всередині функції, може бути повторно використаний.

   Набагато простіше змінити або оновити код в функції (що виконується один раз), ніж шукати і змінювати всі частини коду у функції main() “на місці”. Дублювання коду — хороший рецепт для отримання помилок і погіршення продуктивності.

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

   У функціях підтримується перевірка типів даних для гарантії того, що передані аргументи є коректними відповідно до параметрів функції.

   Функції покращують відлагодження вашої програми.

Однак, одним з головних недоліків використання функцій є те, що при кожному їх виклику відбувається витрата ресурсів, що впливає на продуктивність програми. Це пов’язано з тим, що ЦП повинен зберігати адресу поточної команди (інструкції або стейтменту), яку він виконує (щоб знати, куди потрібно буде повернутися пізніше), разом з іншими даними. Після цього точка виконання переміщується в інше місце програми. Далі всі параметри функції повинні бути створені і їм повинні бути присвоєні значення. І тільки потім, після виконання функції, точка виконання повертається назад. Код, написаний “на місці”, виконується значно швидше.

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

Мова C++ пропонує можливість поєднати всі переваги функцій разом з високою продуктивністю коду, написаного “на місці”. Йдеться про вбудовані функції. Ключове слово inline використовується для запиту, щоб компілятор розглядав вашу функцію як вбудовану. При компіляції вашого коду, всі вбудовані функції (англ. “inline functions”) розкриваються “на місці”, тобто виклик функції замінюється копією вмісту самої функції, і ресурси, які могли б бути витрачені на виклик цієї функції, зберігаються! Мінусом є лише збільшення компільованого коду за рахунок того, що вбудована функція розкривається в коді при кожному її виклику (особливо якщо вона довга і/або її викликають багато разів). Розглянемо наступний фрагмент коду:

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

Тепер, при компіляції функції main(), ЦП читатиме код наступним чином:

Такий код виконається швидше ціною збільшеного об’єму.

Через можливість подібного «роздування», вбудовані функції найкраще використовувати тільки для коротких функцій (не більше декількох рядків коду), які зазвичай викликаються всередині циклів і не мають розгалужень. Також, зверніть увагу, що ключове слово inline є лише рекомендацією — компілятор може проігнорувати ваш запит на вбудовану функцію. Подібне станеться, якщо ви спробуєте зробити довгу функцію вбудованою!

Сучасні компілятори автоматично конвертують відповідні функції у вбудовані — цей процес автоматизований настільки, що навіть краще ручної вибіркової конвертації програмістом. Навіть якщо ви не позначите функцію як вбудовану, компілятор автоматично виконає її як таку, якщо вважатиме, що це сприятиме поліпшенню продуктивності. Таким чином, в більшості випадків немає особливої необхідності використовувати ключове слово inline. Компілятор все зробить сам.

Правило: Якщо ви використовуєте сучасний компілятор, то немає необхідності використовувати ключове слово inline.

Вбудовані функції звільняються від “правила одного визначення”

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

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

Зараз це все може здатися нецікавими дрібницями, але трохи пізніше, коли ми будемо розглядати новий тип функцій (дружні функції), ці дрібниці знадобляться. І пам’ятайте, що навіть з використанням вбудованих функцій, ви НЕ повинні визначати глобальні функції в заголовкових файлах.

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

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

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

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