C++ ponuja vgrajene funkcije za zmanjšanje stroškov klicev funkcij. Funkcija v vrstici je funkcija, ki se ob klicu razširi v vrstico. Ko je funkcija v vrstici poklicana, se celotna koda funkcije v vrstici vstavi ali nadomesti na točki klica funkcije v vrstici. To zamenjavo izvede prevajalnik C++ med prevajanjem. Vgrajena funkcija lahko poveča učinkovitost, če je majhna.
Sintaksa:
inline return-type function-name(parameters) { // function code }>
Ne pozabite, da je vstavljanje le zahteva za prevajalnik in ne ukaz. Prevajalnik lahko prezre zahtevo za vstavljanje.
Prevajalnik ne sme izvajati vstavljanja v naslednjih okoliščinah:
- Če funkcija vsebuje zanko. ( for, while in do-while )
- Če funkcija vsebuje statične spremenljivke.
- Če je funkcija rekurzivna.
- Če vrsta vrnitve funkcije ni void in stavek return ne obstaja v telesu funkcije.
- Če funkcija vsebuje stavek switch ali goto.
Zakaj se uporabljajo vgrajene funkcije?
Ko program izvede ukaz za klic funkcije, CPE shrani pomnilniški naslov ukaza, ki sledi klicu funkcije, kopira argumente funkcije na sklad in končno prenese nadzor na določeno funkcijo. CPE nato izvede kodo funkcije, shrani vrnjeno vrednost funkcije na vnaprej določeno pomnilniško lokacijo/register in vrne nadzor klicni funkciji. To lahko povzroči dodatne stroške, če je čas izvajanja funkcije krajši od časa preklopa s klicne funkcije na klicano funkcijo (klicanec).
Za funkcije, ki so velike in/ali izvajajo zapletene naloge, je strošek klica funkcije običajno nepomemben v primerjavi s časom, ki ga funkcija potrebuje za izvajanje. Vendar je pri majhnih, pogosto uporabljenih funkcijah čas, potreben za klic funkcije, pogosto veliko daljši od časa, potrebnega za dejansko izvedbo kode funkcije. Ta obremenitev nastane pri majhnih funkcijah, ker je čas izvajanja majhne funkcije krajši od časa preklopa.
Inline funkcije Prednosti:
- Ne pride do dodatnih stroškov pri klicu funkcije.
- Prav tako prihrani stroške spremenljivk push/pop na skladu, ko je funkcija poklicana.
- Prav tako prihrani režijske stroške povratnega klica funkcije.
- Ko vstavite funkcijo, lahko prevajalniku omogočite, da izvede optimizacijo, specifično za kontekst, v telesu funkcije. Takšne optimizacije niso možne za običajne klice funkcij. Druge optimizacije je mogoče doseči z upoštevanjem tokov klicnega konteksta in klicanega konteksta.
- Inline funkcija je lahko uporabna (če je majhna) za vgrajene sisteme, ker lahko inline vrne manj kode kot funkcija, imenovana preambula in return.
Vgrajena funkcija Slabosti:
- Dodane spremenljivke iz vstavljene funkcije porabijo dodatne registre. Če se po funkciji vstavitve število spremenljivk, ki bo uporabljala register, poveča, lahko povzročijo dodatne stroške pri uporabi virov spremenljivke registra. To pomeni, da ko je telo funkcije v vrstici zamenjano na točki klica funkcije, se vstavi tudi skupno število spremenljivk, ki jih uporablja funkcija. Tako se bo povečalo tudi število registrov, ki bodo uporabljeni za spremenljivke. Torej, če se po vstavitvi funkcij številke spremenljivk drastično povečajo, bi to zagotovo povzročilo dodatne stroške pri uporabi registra.
- Če uporabljate preveč vgrajenih funkcij, bo velikost binarne izvršljive datoteke velika zaradi podvajanja iste kode.
- Preveč vstavljanja lahko tudi zmanjša vašo stopnjo zadetkov predpomnilnika navodil, s čimer se zmanjša hitrost pridobivanja navodil iz predpomnilnika v primarni pomnilnik.
- Vgrajena funkcija lahko poveča čas prevajanja, če nekdo spremeni kodo znotraj vgrajene funkcije, potem je treba vso klicno lokacijo znova prevesti, ker bi moral prevajalnik znova zamenjati vso kodo, da odraža spremembe, sicer bo nadaljeval s starim funkcionalnost.
- Vgrajene funkcije morda niso uporabne za mnoge vgrajene sisteme. Ker je v vgrajenih sistemih velikost kode pomembnejša od hitrosti.
- Funkcije v vrstici lahko povzročijo razbijanje, ker lahko vdelava poveča velikost binarne izvršljive datoteke. Zmanjšanje pomnilnika povzroči poslabšanje delovanja računalnika. Naslednji program prikazuje uporabo funkcije inline.
primer:
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;> }> |
>
>Izhod
The cube of 3 is: 27>
Vgrajena funkcija in razredi
Možno je tudi definirati inline funkcijo znotraj razreda. Pravzaprav so vse funkcije, definirane znotraj razreda, implicitno vgrajene. Tako se tudi tukaj uporabljajo vse omejitve inline funkcij. Če morate eksplicitno deklarirati inline funkcijo v razredu, potem preprosto deklarirajte funkcijo znotraj razreda in jo definirajte zunaj razreda s ključno besedo inline.
Sintaksa:
class S { public: inline int square(int s) // redundant use of inline { // this function is automatically inline // function body } };> Zgornji slog velja za slab stil programiranja. Najboljši slog programiranja je, da samo napišete prototip funkcije znotraj razreda in ga podate kot vstavljeno vrstico v definiciji funkcije.
Na primer:
class S { public: int square(int s); // declare the function }; inline int S::square(int s) // use inline prefix { }> primer:
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;> }> |
>
vb in vb net
>
Izhod:
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>
Kaj je narobe z makrom?
Bralci, ki poznajo jezik C, vedo, da jezik C uporablja makro. Predprocesor nadomesti vse klice makra neposredno znotraj kode makra. Priporočljivo je, da namesto makra vedno uporabite vgrajeno funkcijo. Po besedah dr. Bjarna Stroustrupa ustvarjalec C++ makri skoraj nikoli niso potrebni v C++ in so nagnjeni k napakam. Obstaja nekaj težav z uporabo makrov v C++. Makro ne more dostopati do zasebnih članov razreda. Makri so videti kot funkcijski klici, vendar v resnici niso.
primer:
C++
// C++ Program to demonstrate working of macro> #include> using> namespace> std;> class> S {> >int> m;> public>:> >// error> #define MAC(S::m)> };> |
>
>
Izhod:
Error: '::' may not appear in macro parameter list #define MAC(S::m)>
Prevajalnik C++ preveri vrste argumentov vgrajenih funkcij in se potrebne pretvorbe izvedejo pravilno. Makro predprocesorja tega ne zmore. Druga stvar je, da makre upravlja predprocesor, inline funkcije pa prevajalnik C++. Ne pozabite: res je, da so vse funkcije, definirane znotraj razreda, implicitno vgrajene in bo prevajalnik C++ izvedel vgrajene klice teh funkcij, vendar prevajalnik C++ ne more izvesti v vrstici, če je funkcija navidezna. Razlog, da je poklicana navidezna funkcija, se razreši med izvajanjem namesto med prevajanjem. Virtualno pomeni čakanje na čas izvajanja in inline pomeni med prevajanjem, če prevajalnik ne ve, katera funkcija bo poklicana, kako lahko izvede inline? Še ena stvar, ki si jo morate zapomniti, je, da je koristno narediti funkcijo inline samo, če je čas, porabljen med klicem funkcije, večji od časa izvajanja telesa funkcije.
Primer, kjer vgrajena funkcija sploh nima učinka:
inline void show() { cout << 'value of S = ' << S << endl; }> Izvedba zgornje funkcije traja relativno dolgo. Na splošno funkcija, ki izvaja vhodno-izhodno (I/O) operacijo, ne bi smela biti opredeljena kot vgrajena, ker porabi precej časa. Tehnično vstavljanje funkcije show() ima omejeno vrednost, ker čas, ki ga bo vzel V/I stavek, močno presega stroške klica funkcije. Odvisno od prevajalnika, ki ga uporabljate, vam lahko prevajalnik prikaže opozorilo, če funkcija ni razširjena v vrstici.
Programski jeziki, kot sta Java in C#, ne podpirajo vgrajenih funkcij. Toda v Javi lahko prevajalnik izvede vstavljanje, ko se kliče majhna končna metoda, ker podrazredi ne morejo preglasiti končnih metod, klic končne metode pa se razreši med prevajanjem.
V C# prevajalnik JIT lahko tudi optimizira kodo z vstavljanjem klicev majhnih funkcij (na primer zamenjava telesa majhne funkcije, ko je klicana v zanki). Zadnja stvar, ki jo morate imeti v mislih, je, da so vgrajene funkcije dragocena lastnost C++. Ustrezna uporaba vgrajenih funkcij lahko zagotovi izboljšanje zmogljivosti, vendar če se vgrajene funkcije uporabljajo samovoljno, ne morejo zagotoviti boljših rezultatov. Z drugimi besedami, ne pričakujte boljšega delovanja programa. Ne naredite vsake funkcije vstavljene. Bolje je, da so vgrajene funkcije čim manjše.