C++ poskytuje inline funkcie na zníženie réžie volania funkcií. Inline funkcia je funkcia, ktorá sa pri volaní rozšíri v riadku. Keď sa volá inline funkcia, celý kód inline funkcie sa vloží alebo nahradí v bode volania inline funkcie. Túto substitúciu vykonáva kompilátor C++ v čase kompilácie. Inline funkcia môže zvýšiť efektivitu, ak je malá.
Syntax:
inline return-type function-name(parameters) { // function code }>
Pamätajte, že vkladanie je len požiadavka pre kompilátor, nie príkaz. Kompilátor môže ignorovať požiadavku na vloženie.
Kompilátor nesmie vykonávať vkladanie za takých okolností, ako sú:
- Ak funkcia obsahuje slučku. ( na, kým a kým )
- Ak funkcia obsahuje statické premenné.
- Ak je funkcia rekurzívna.
- Ak je návratový typ funkcie iný ako void a príkaz return neexistuje v tele funkcie.
- Ak funkcia obsahuje príkaz switch alebo goto.
Prečo sa používajú inline funkcie?
Keď program vykoná inštrukciu volania funkcie, CPU uloží pamäťovú adresu inštrukcie nasledujúcej po volaní funkcie, skopíruje argumenty funkcie do zásobníka a nakoniec prenesie riadenie na špecifikovanú funkciu. CPU potom vykoná kód funkcie, uloží návratovú hodnotu funkcie do preddefinovaného pamäťového miesta/registra a vráti riadenie volajúcej funkcii. Toto sa môže stať réžiou, ak je čas vykonania funkcie kratší ako čas prepnutia z funkcie volajúceho na volanú funkciu (volaný).
Pre funkcie, ktoré sú veľké a/alebo vykonávajú zložité úlohy, je réžia volania funkcie zvyčajne nepodstatná v porovnaní s časom, ktorý funkcia potrebuje na spustenie. V prípade malých, bežne používaných funkcií je však čas potrebný na uskutočnenie volania funkcie často oveľa dlhší ako čas potrebný na skutočné vykonanie kódu funkcie. Táto réžia sa vyskytuje pri malých funkciách, pretože čas vykonania malej funkcie je kratší ako čas spínania.
Inline funkcie Výhody:
- Režijné volanie funkcie sa nevyskytuje.
- Pri volaní funkcie tiež šetrí réžiu premenných push/pop v zásobníku.
- Tiež šetrí réžiu spätného volania z funkcie.
- Keď vložíte funkciu, môžete povoliť kompilátoru vykonávať kontextovo špecifickú optimalizáciu v tele funkcie. Takéto optimalizácie nie sú možné pre normálne volania funkcií. Ďalšie optimalizácie možno získať zvážením tokov volajúceho kontextu a volaného kontextu.
- Inline funkcia môže byť užitočná (ak je malá) pre vstavané systémy, pretože inline môže poskytnúť menej kódu ako funkcia nazývaná preambula a návrat.
Inline funkcie Nevýhody:
- Pridané premenné z inline funkcie spotrebúvajú ďalšie registre. Po in-line funkcii, ak sa zvýši počet premennej, ktorá bude používať register, môžu vytvárať réžiu na využitie zdrojov premenných registrov. To znamená, že keď sa telo funkcie v riadku nahradí v bode volania funkcie, vloží sa aj celkový počet premenných, ktoré funkcia používa. Zvýši sa teda aj počet registrov, ktoré sa budú používať pre premenné. Takže ak sa po funkcii vloženia čísel premenných drasticky zvýšia, potom by to určite spôsobilo réžiu pri využití registra.
- Ak použijete príliš veľa inline funkcií, veľkosť binárneho spustiteľného súboru bude veľká kvôli duplikácii rovnakého kódu.
- Príliš veľa vkladania môže tiež znížiť rýchlosť prístupu do vyrovnávacej pamäte inštrukcií, čím sa zníži rýchlosť načítania inštrukcie z pamäte cache na rýchlosť primárnej pamäte.
- Vložená funkcia môže zvýšiť réžiu času kompilácie, ak niekto zmení kód vo vnútri inline funkcie, potom sa musí prekompilovať celé miesto volania, pretože kompilátor by musel znova nahradiť celý kód, aby odrážal zmeny, inak bude pokračovať so starým funkčnosť.
- Inline funkcie nemusia byť užitočné pre mnohé vstavané systémy. Pretože vo vstavaných systémoch je veľkosť kódu dôležitejšia ako rýchlosť.
- Vložené funkcie môžu spôsobiť rušenie, pretože vloženie môže zväčšiť veľkosť binárneho spustiteľného súboru. Prebíjanie pamäte spôsobuje zníženie výkonu počítača. Nasledujúci program demonštruje použitie funkcie inline.
Príklad:
C++
#include> using> namespace> std;> inline> int> cube(>int> s) {>return> s * s * s; }> int> main()> {> >cout <<>'The cube of 3 is: '> << cube(3) <<>'
'>;> >return> 0;> }> |
>
>Výkon
The cube of 3 is: 27>
Inline funkcia a triedy
Vo vnútri triedy je tiež možné definovať inline funkciu. V skutočnosti sú všetky funkcie definované vo vnútri triedy implicitne vložené. Aj tu sa teda uplatňujú všetky obmedzenia inline funkcií. Ak potrebujete explicitne deklarovať inline funkciu v triede, potom stačí deklarovať funkciu vo vnútri triedy a definovať ju mimo triedy pomocou kľúčového slova inline.
Syntax:
class S { public: inline int square(int s) // redundant use of inline { // this function is automatically inline // function body } };> Vyššie uvedený štýl sa považuje za zlý štýl programovania. Najlepším štýlom programovania je jednoducho napísať prototyp funkcie do triedy a špecifikovať ho ako inline v definícii funkcie.
Napríklad:
class S { public: int square(int s); // declare the function }; inline int S::square(int s) // use inline prefix { }> Príklad:
C++
// C++ Program to demonstrate inline functions and classes> #include> using> namespace> std;> class> operation {> >int> a, b, add, sub, mul;> >float> div>;> public>:> >void> get();> >void> sum();> >void> difference();> >void> product();> >void> division();> };> inline> void> operation ::get()> {> >cout <<>'Enter first value:'>;> >cin>> a;> >cout <<>'Enter second value:'>;> >cin>> b;> }> inline> void> operation ::sum()> {> >add = a + b;> >cout <<>'Addition of two numbers: '> << a + b <<>'
'>;> }> inline> void> operation ::difference()> {> >sub = a - b;> >cout <<>'Difference of two numbers: '> << a - b <<>'
'>;> }> inline> void> operation ::product()> {> >mul = a * b;> >cout <<>'Product of two numbers: '> << a * b <<>'
'>;> }> inline> void> operation ::division()> {> >div> = a / b;> >cout <<>'Division of two numbers: '> << a / b <<>'
'>;> }> int> main()> {> >cout <<>'Program using inline function
'>;> >operation s;> >s.get();> >s.sum();> >s.difference();> >s.product();> >s.division();> >return> 0;> }> |
>
java otváranie súboru
>
Výkon:
Enter first value: 45 Enter second value: 15 Addition of two numbers: 60 Difference of two numbers: 30 Product of two numbers: 675 Division of two numbers: 3>
Čo je zlé na makre?
Čitatelia oboznámení s jazykom C vedia, že jazyk C používa makro. Preprocesor nahrádza všetky volania makra priamo v kóde makra. Namiesto makra sa odporúča vždy použiť inline funkciu. Podľa Dr. Bjarne Stroustrupa, tvorca makier C++ nie je v C++ takmer nikdy potrebný a sú náchylné na chyby. Pri používaní makier v C++ sú určité problémy. Makro nemá prístup k súkromným členom triedy. Makrá vyzerajú ako volania funkcií, ale v skutočnosti nie sú.
Príklad:
C++
// C++ Program to demonstrate working of macro> #include> using> namespace> std;> class> S {> >int> m;> public>:> >// error> #define MAC(S::m)> };> |
>
>
Výkon:
Error: '::' may not appear in macro parameter list #define MAC(S::m)>
Kompilátor C++ skontroluje typy argumentov inline funkcií a potrebné konverzie sa vykonajú správne. Makro preprocesora to nedokáže. Ďalšou vecou je, že makrá sú riadené preprocesorom a inline funkcie sú riadené kompilátorom C++. Pamätajte: Je pravda, že všetky funkcie definované vo vnútri triedy sú implicitne vložené a kompilátor C++ bude vykonávať inline volania týchto funkcií, ale kompilátor C++ nemôže vykonávať inline, ak je funkcia virtuálna. Dôvod, prečo je volaná virtuálna funkcia, je vyriešený za behu namiesto kompilácie. Virtuálne znamená čakať na runtime a inline znamená počas kompilácie, ak kompilátor nevie, ktorá funkcia sa bude volať, ako môže vykonať inlining? Ďalšou vecou, ktorú si treba zapamätať, je, že je užitočné vložiť funkciu iba vtedy, ak je čas strávený počas volania funkcie viac v porovnaní s časom vykonania tela funkcie.
Príklad, keď funkcia inline nemá vôbec žiadny účinok:
inline void show() { cout << 'value of S = ' << S << endl; }> Vyššie uvedená funkcia trvá relatívne dlho. Vo všeobecnosti by funkcia, ktorá vykonáva vstupno-výstupnú (I/O) operáciu, nemala byť definovaná ako inline, pretože trávi značné množstvo času. Technicky vloženie funkcie show() má obmedzenú hodnotu, pretože čas, ktorý I/O príkaz zaberie, ďaleko presahuje réžiu volania funkcie. V závislosti od kompilátora, ktorý používate, vám kompilátor môže zobraziť varovanie, ak funkcia nie je rozšírená inline.
Programovacie jazyky ako Java a C# nepodporujú inline funkcie. Ale v jazyku Java môže kompilátor vykonať inlining, keď sa volá malá konečná metóda, pretože konečné metódy nemožno prepísať podtriedami a volanie konečnej metódy je vyriešené v čase kompilácie.
V C# JIT kompilátor môže tiež optimalizovať kód vložením malých volaní funkcií (ako je nahradenie tela malej funkcie, keď je volaná v slučke). Posledná vec, ktorú treba mať na pamäti, je, že inline funkcie sú cennou vlastnosťou C++. Vhodné použitie inline funkcií môže poskytnúť zvýšenie výkonu, ale ak sa inline funkcie používajú svojvoľne, nemôžu poskytnúť lepšie výsledky. Inými slovami, neočakávajte lepší výkon programu. Nerobte všetky funkcie inline. Je lepšie ponechať inline funkcie čo najmenšie.