Я знаю, що inline - це підказка або запит до компілятора і використовується для уникнення накладних викликів функцій.
Тож на якій основі можна визначити, є функція кандидатом на вбудоване чи ні? У якому випадку слід уникати вкладки?
Я знаю, що inline - це підказка або запит до компілятора і використовується для уникнення накладних викликів функцій.
Тож на якій основі можна визначити, є функція кандидатом на вбудоване чи ні? У якому випадку слід уникати вкладки?
Відповіді:
Уникнути вартості функціонального дзвінка - це лише половина історії.
робити:
inline
замість#define
inline
: швидшого коду та менших виконуваних файлів (більше шансів залишитися в кеш-коді)не:
розробляючи бібліотеку, щоб зробити клас розширюваним у майбутньому, слід:
Пам'ятайте, що inline
ключове слово є натяком на компілятор: компілятор може вирішити не вбудовувати функцію, і він може вирішити вбудовані функції, які не були позначені inline
в першу чергу. Я взагалі уникаю функції маркування inline
(крім того, можливо, коли пишуть дуже маленькі функції).
Щодо продуктивності, розумним підходом є (як завжди) профілювання програми, а згодом inline
набір функцій, що представляють вузьке місце.
Список літератури:
EDIT: Bjarne Stroustrup, Мова програмування на C ++:
Функція може бути визначена як
inline
. Наприклад:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
Специфікатор
inline
є натяком компілятору, що він повинен намагатися генерувати код дляfac()
вбудованого виклику, а не встановлювати код для функції один раз, а потім викликати через звичайний механізм виклику функції. Розумний компілятор може генерувати константу720
для дзвінкаfac(6)
. Можливість взаємно рекурсивних вбудованих функцій, вбудованих функцій, які повторюються або не залежать від введення тощо, не дає можливості гарантувати, що кожен викликinline
функції насправді є вкладеним. Ступінь чіткості компілятора не може бути законодавчо встановлений, тому один компілятор може генерувати720
, інший6 * fac(5)
, а ще один невкладений дзвінокfac(6)
.Щоб зробити вбудовування можливим за відсутності незвично розумних засобів компіляції та зв’язування, визначення - а не лише декларування - функції вбудованої функції повинно бути в межах сфери (§ 9.2).
inline
Especifier не впливає на семантику функції. Зокрема, вбудована функція все ще має унікальну адресу і тому маєstatic
змінні (§ 7.1.2) вбудованої функції.
EDIT2: ISO-IEC 14882-1998, 7.1.2 Специфікатори функції
Оголошення функції (8.3.5, 9.3, 11.4) із
inline
специфікатором оголошує вбудовану функцію. Вбудований специфікатор вказує на реалізацію, що заміна вбудованого функції функції в точці виклику повинна віддавати перевагу звичайному механізму виклику функції. Не потрібно реалізовувати для виконання цієї заміни вбудовані в точці виклику; однак, навіть якщо ця заміна вбудованої лінії опущена, інші правила для функцій вбудованого рівня, визначені 7.1.2, все ще повинні дотримуватися.
inline
набагато більше, ніж натяк на компілятор. Це змінює мовні правила щодо кількох визначень. Також статичні дані - це не чавунна причина, щоб уникнути вбудовування функції. Реалізація зобов'язана виділити один статичний об'єкт для кожної статичної функції, незалежно від того, оголошена функція inline
чи ні. Класи все ще розширюються, якщо вони мають вбудовані конструктори та віртуальні деструктори. І порожній брекет-деструктор - це одна віртуальна функція, яку іноді корисно залишити в рядку.
inline
, то результат полягає в тому, що функція не буде вбудована: ви платите ціну за дзвінок, а також кожен блок перекладу, який включає та викликує функцію, отримує власну копію коду та статичних змінних. Причиною не вбудовування конструкторів та деструкторів при розробці бібліотеки є двійкова сумісність із майбутніми версіями вашої бібліотеки
inline
можна накреслити, якщо компілятор відчуває це. І inline
функції не будуть накреслені, якщо компілятор вирішить їх не вбудовувати. Як сказав Чарльз Бейлі, це змінює мовні правила. Замість того, щоб думати про це як натяк на оптимізацію, точніше мислити це як зовсім інше поняття. inline
Ключове слово вказує компілятору дозволити кілька визначень, і більше нічого. Оптимізація "вбудовування" може застосовуватися майже до будь-якої функції, незалежно від того, позначена вона чи ні inline
.
inline
для отримання вбудованої функції. Іноді ми хочемо інших переваг, таких як обхід ODR.
inline
має дуже мало спільного з оптимізацією. inline
- це інструкція компілятору не створювати помилок, якщо функція, що задається функцією, виникає кілька разів у програмі, і обіцяє, що визначення відбудеться в кожному перекладі, який він використовується, і скрізь, де воно з'явиться, воно буде мати абсолютно те саме визначення.
З огляду на вищезазначені правила, inline
підходить для коротких функцій, тіло яких не потребує включення додаткових залежностей від того, що потрібно лише декларації. Кожного разу, коли виникає визначення, його слід проаналізувати і код його тіла може бути сформований, тому він передбачає деякий накладний набір компілятора над функцією, визначеною лише один раз у одному вихідному файлі.
Компілятор може вбудувати (тобто замінити виклик функції на код, який виконує цю дію цієї функції) будь-який виклик функції, який він обрав. Раніше це було так, що він "очевидно" не міг вбудувати функцію, яка не була оголошена в тому ж блоці перекладу, що і виклик, але при збільшенні використання оптимізації часу зв'язку навіть це зараз не вірно. Не менш правдивим є той факт, що позначені функції inline
можуть бути не окреслені .
inline
ключовим словом? А що таке щасливий збіг?
Розповідати компілятору про вбудовану функцію - це оптимізація, і найважливіше правило оптимізації полягає в тому, що передчасна оптимізація є коренем усього зла. Завжди пишіть чіткий код (використовуючи ефективні алгоритми), потім профіліруйте свою програму та лише оптимізуйте функції, які займають занадто багато часу.
Якщо ви виявите, що певна функція є дуже короткою і простою, і її викликають десятки тисяч разів у тісному внутрішньому циклі, це може бути хорошим кандидатом.
Можливо, ви здивуєтеся - багато компіляторів C ++ автоматично вбудують для вас невеликі функції - і вони також можуть проігнорувати ваш запит на вбудовану лінію.
/FAcs
у Visual Studio, -s
в GCC), щоб побачити, що саме він робить. На мій досвід, обидва ці компілятори досить сильно оцінюють вбудоване ключове слово.
inline
ключове слово. Тобто, якщо ви бачите, що функція є вбудованою, і вилучите inline
з неї специфікатор, вона все одно стане вбудованою. Якщо у вас є конкретні приклади протилежного, будь ласка, поділіться ними!
inline
ключове слово перешкоджає "очистити код"? Ключове слово в "передчасна оптимізація" - передчасна , а не оптимізація. Говорити, що слід активно * уникати оптимізацій - це лише сміття. Суть цієї цитати полягає в тому, що вам слід уникати оптимізацій, які можуть не бути необхідними, і мати шкідливі побічні ефекти на код (наприклад, зробити його менш рентабельним). Я не бачу, як inline
ключове слово зробить код менш рентабельним, або як це може бути шкідливо додати його до функції.
Найкращий спосіб дізнатися це - профілювати свою програму та відзначати невеликі функції, які називаються багато разів і записуються через цикли процесора inline
. Ключове слово тут "мале" - коли накладні витрати виклику функцій є незначними порівняно з часом, проведеним у функції, їх безглуздо вбудовувати.
Інше використання, яке я пропоную, - це якщо у вас є невеликі функції, які викликають критичний код продуктивності досить часто, щоб зробити кеш-пропуском відповідним, ви, ймовірно, повинні також вбудувати їх. Знову ж таки, це те, що повинен мати тобі промовець.
Передчасна оптимізація - корінь усього зла!
Як правило, я вказую лише "геттери" та "сетери". Після того, як код працює і стабільний, профілювання може показати, які функції можуть отримати користь від вбудовування.
З іншого боку, більшість сучасних компіляторів мають досить хороші алгоритми оптимізації, і вони будуть вказувати те, що ви повинні мати для вас.
Повторне відновлення - пишіть вбудовані функції з одним вкладишем і пізніше переживайте за інших.
Вбудовані функції можуть підвищити продуктивність вашого коду, усунувши необхідність проштовхувати аргументи в стек. якщо відповідна функція знаходиться у критичній частині вашого коду, ви повинні прийняти вбудоване не вбудоване рішення в частині оптимізації вашого проекту,
ви можете прочитати більше про рядки у файлі c ++
Я, як правило, дотримуюся правила великого пальця, де я виконую функцію з 3-4 простими висловлюваннями як вбудовані. Але добре пам’ятати, що це лише натяк на компілятора. Остаточний виклик, щоб зробити його вбудованим чи ні, приймається лише компілятором. Якщо таких заяв більше, я не оголошу вбудований текст, оскільки з дурним компілятором це може призвести до роздуття коду.
Приймаючи рішення про те, чи потрібно використовувати вбудований, я зазвичай маю на увазі таке уявлення: На сучасних машинах затримка пам’яті може бути більшим місцем, ніж сирі розрахунки. Функції вбудовування, які називаються часто, як відомо, збільшують розмір виконуваних файлів. Крім того, така функція може бути збережена в кеш-коді центрального процесора, що зменшить кількість пропусків кешу, коли потрібно отримати доступ до цього коду.
Отже, ви повинні вирішити для себе: чи збільшує чи зменшує розмір створюваного машинного коду розмір? Наскільки ймовірно, що виклик функції призведе до пропуску кешу? Якщо він перецьовується у всьому коді, то я б сказав, що ймовірність висока. Якщо вона обмежена однією тісною петлею, то ймовірність, мабуть, мала.
Я зазвичай використовую вкладки у випадках, які я перелічу нижче. Однак, коли ви щиро заклопотані результатами, профайлінг має важливе значення. Крім того, ви можете перевірити, чи компілятор насправді приймає підказку.
Також вбудований метод має серйозні побічні ефекти при підтримці великих проектів. Коли змінений вбудований код, усі файли, які його використовують, буде відновлено автоматично компілятором (це хороший компілятор). Це може витратити багато часу на розвиток.
Коли inline
метод переноситься у вихідний файл і більше не вказується, весь проект повинен бути перебудований (принаймні, це був мій досвід). А також коли методи перетворюються на вбудовані.
inline
чи ні, не має значення (окрім як без inline
ключового слова, ви отримаєте помилки в посиланнях, але inline
ключове слово не є проблемою, що спричиняє надмірні перебудови.
Якщо ви думаєте, що ваш код є досить малим, щоб його можна було використовувати як вбудований, і запам'ятовуйте вбудовану функцію, дублюючи код і вставляйте його, коли функція викликається, тому це може бути досить гарним, щоб збільшити час виконання, але також збільшити споживання пам'яті. Ви не можете використовувати вбудовану функцію, коли ви використовуєте циклічну / статичну змінну / рекурсивну / комутатор / гото / віртуальну функцію. Віртуальні засоби чекають, поки час виконання та вбудовані засоби під час компіляції, щоб їх не можна було використовувати одночасно.
Я прочитав кілька відповідей і бачу, що там відсутні деякі речі.
Правило, яке я використовую, - це не використовувати вбудований, якщо тільки я не хочу, щоб воно було вбудованим. Виглядає дурно, тепер пояснення.
Компілятори досить розумні, і короткі функції завжди роблять вбудованими. І ніколи не виконує функцію тривалості як вбудований, якщо програміст не сказав цього робити.
Я знаю, що inline - це підказка або запит до компілятора
Насправді inline
це замовлення для компілятора, він не має вибору і після inline
ключового слова робить весь код вбудованим. Таким чином, ви ніколи не можете використовувати inline
ключове слово, і компілятор створить найкоротший код.
То коли використовувати inline
?
Щоб використовувати, якщо ви хочете мати якийсь код вбудований. Я знаю лише один приклад, тому що використовую його лише в одній ситуації. Це аутентифікація користувача.
Наприклад, у мене є така функція:
inline bool ValidUser(const std::string& username, const std::string& password)
{
//here it is quite long function
}
Незалежно від того, наскільки великою є ця функція, я хочу мати її як вбудовану, тому що це робить моє програмне забезпечення важче зламати.
inline
- це для прибульця C ++, щоCFLAGS
стосується прибульця Gentoo: ні, компіляція з цим-O3 -funroll-loops -finline-functions
не змусить літати ваш старий Pentium;)