logo

Įterptosios funkcijos C++

C++ suteikia tiesiogines funkcijas, kad sumažintų funkcijų skambučio išlaidas. Inline funkcija yra funkcija, kuri išplečiama eilutėje, kai ji iškviečiama. Kai įterptoji funkcija vadinama, visas eilutinės funkcijos kodas įterpiamas arba pakeičiamas eilutinės funkcijos iškvietimo vietoje. Šį pakeitimą kompiliavimo metu atlieka C++ kompiliatorius. Inline funkcija gali padidinti efektyvumą, jei ji yra maža.

Sintaksė:



inline return-type function-name(parameters) { // function code }>
Inline funkcija c++

Atminkite, kad įtraukimas yra tik užklausa kompiliatoriui, o ne komanda. Kompiliatorius gali nepaisyti įterpimo užklausos.

Kompiliatorius negali atlikti įtraukimo tokiomis aplinkybėmis kaip:

  1. Jei funkcijoje yra ciklas. ( už, kol ir daryti-kol )
  2. Jei funkcijoje yra statinių kintamųjų.
  3. Jei funkcija yra rekursinė.
  4. Jei funkcijos grąžinimo tipas yra kitoks nei void, o grąžinimo teiginio funkcijos turinyje nėra.
  5. Jei funkcijoje yra jungiklis arba goto sakinys.

Kodėl naudojamos tiesioginės funkcijos?

Kai programa vykdo funkcijos iškvietimo komandą, centrinis procesorius išsaugo po funkcijos iškvietimo einančios komandos adresą, nukopijuoja funkcijos argumentus krūvelėje ir galiausiai perduoda valdymą nurodytai funkcijai. Tada CPU vykdo funkcijos kodą, išsaugo funkcijos grąžinimo reikšmę iš anksto nustatytoje atminties vietoje / registre ir grąžina iškvietimo funkcijos valdymą. Tai gali tapti nereikalinga, jei funkcijos vykdymo laikas yra trumpesnis nei perjungimo iš skambintojo funkcijos į iškviestą funkciją (skambintoją) laikas.



Funkcijoms, kurios yra didelės ir (arba) atlieka sudėtingas užduotis, funkcijos iškvietimo išlaidos paprastai yra nereikšmingos, palyginti su laiku, per kurį funkcija paleidžiama. Tačiau mažoms, dažniausiai naudojamoms funkcijoms laikas, reikalingas funkcijos iškvietimui, dažnai yra daug ilgesnis nei laikas, reikalingas iš tikrųjų atlikti funkcijos kodą. Šios papildomos išlaidos atsiranda mažoms funkcijoms, nes mažos funkcijos vykdymo laikas yra trumpesnis nei perjungimo laikas.

Inline funkcijos Privalumai:

  1. Funkcijos skambučio pridėtinės išlaidos nevyksta.
  2. Taip pat išsaugoma krūvoje esančių push/pop kintamųjų pridėtinė suma, kai iškviečiama funkcija.
  3. Taip pat sutaupoma papildomos funkcijos grįžtamojo skambučio išlaidos.
  4. Kai įtraukiate funkciją, galite įgalinti kompiliatorių atlikti konkrečios funkcijos konteksto optimizavimą. Tokie optimizavimai neįmanomi įprastų funkcijų skambučiams. Kitus optimizavimus galima gauti įvertinus skambinimo konteksto ir iškviečiamo konteksto srautus.
  5. Įterptoji funkcija gali būti naudinga (jei ji maža) įterptosiose sistemose, nes įterptoji funkcija gali duoti mažiau kodo nei funkcija, vadinama preambule ir grąžinimu.

Inline funkcijos trūkumai:

  1. Pridedami kintamieji iš įtrauktosios funkcijos sunaudoja papildomus registrus. Po įterptosios funkcijos, jei padidėja registrą naudojančių kintamųjų skaičius, jie gali sukurti papildomų registro kintamųjų išteklių naudojimo išlaidų. Tai reiškia, kad kai funkcijos iškvietimo taške pakeičiamas eilutės funkcijos turinys, taip pat įterpiamas visas funkcijos naudojamų kintamųjų skaičius. Taigi registrų, kurie bus naudojami kintamiesiems, skaičius taip pat padidės. Taigi, jei po funkcijos įtraukimo kintamųjų skaičiai drastiškai padidėtų, tai neabejotinai padidins registro naudojimą.
  2. Jei naudosite per daug eilutinių funkcijų, dvejetainio vykdomojo failo dydis bus didelis dėl to paties kodo dubliavimo.
  3. Per daug įtraukimo taip pat gali sumažinti instrukcijų talpyklos pataikymo dažnį, taip sumažinant instrukcijų gavimo greitį iš talpyklos atminties į pirminės atminties greitį.
  4. Inline funkcija gali padidinti kompiliavimo laiką, jei kas nors pakeičia kodą eilutinės funkcijos viduje, tada visa iškvietimo vieta turi būti sukompiliuota iš naujo, nes kompiliatorius turės dar kartą pakeisti visą kodą, kad atspindėtų pakeitimus, kitaip jis tęsis su senu funkcionalumą.
  5. Įterptosios funkcijos gali būti nenaudingos daugeliui įterptųjų sistemų. Kadangi įterptosiose sistemose kodo dydis yra svarbesnis už greitį.
  6. Įterptosios funkcijos gali sukelti sumušimą, nes įterpimas gali padidinti dvejetainio vykdomojo failo dydį. Dėl trynimo atmintyje pablogėja kompiuterio našumas. Toliau pateikta programa parodo įterptinės funkcijos naudojimą.

Pavyzdys:

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;> }>

>

>

Išvestis

The cube of 3 is: 27>

Inline funkcija ir klasės

Taip pat klasėje galima apibrėžti tiesioginę funkciją. Tiesą sakant, visos klasės viduje apibrėžtos funkcijos yra netiesiogiai įtrauktos. Taigi čia taip pat taikomi visi inline funkcijų apribojimai. Jei klasėje reikia aiškiai deklaruoti įterptą funkciją, tiesiog deklaruokite funkciją klasėje ir apibrėžkite ją už klasės ribų naudodami įterptinį raktinį žodį.

Sintaksė:

class S { public: inline int square(int s) // redundant use of inline { // this function is automatically inline // function body } };>

Aukščiau pateiktas stilius laikomas blogu programavimo stiliumi. Geriausias programavimo stilius yra tiesiog įrašyti funkcijos prototipą klasėje ir nurodyti jį kaip eilutę funkcijos apibrėžime.

Pavyzdžiui:

class S { public: int square(int s); // declare the function }; inline int S::square(int s) // use inline prefix { }>

Pavyzdys:

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;> }>

>

sujungimas java eilutė
>

Išvestis:

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>

Kas negerai su makrokomandu?

Skaitytojai, susipažinę su C kalba, žino, kad C kalba naudoja makrokomandas. Pirminis procesorius pakeičia visus makrokomandų iškvietimus tiesiai makrokode. Rekomenduojama visada vietoj makrokomandos naudoti įterptąją funkciją. Dr. Bjarne'o Stroustrup teigimu, C++ makrokomandų kūrėjas beveik niekada nėra būtinas C++ ir jose dažnai pasitaiko klaidų. Yra tam tikrų problemų naudojant makrokomandas C++. Makrokomandas negali pasiekti privačių klasės narių. Makrokomandos atrodo kaip funkcijų iškvietimai, bet iš tikrųjų taip nėra.

Pavyzdys:

C++




// C++ Program to demonstrate working of macro> #include> using> namespace> std;> class> S {> >int> m;> public>:> >// error> #define MAC(S::m)> };>

>

>

Išvestis:

Error: '::' may not appear in macro parameter list #define MAC(S::m)>

C++ kompiliatorius patikrina įterptinių funkcijų argumentų tipus ir reikiamos konversijos atliekamos teisingai. Išankstinio procesoriaus makrokomanda to negali padaryti. Kitas dalykas yra tai, kad makrokomandas valdo išankstinis procesorius, o įterptąsias funkcijas valdo C++ kompiliatorius. Atminkite: tiesa, kad visos klasės viduje apibrėžtos funkcijos yra netiesiogiai įtrauktos ir C++ kompiliatorius atliks eilinius šių funkcijų iškvietimus, tačiau C++ kompiliatorius negali atlikti eilinio, jei funkcija yra virtuali. Priežastis, dėl kurios iškviečiama virtualioji funkcija, išsprendžiama vykdymo, o ne kompiliavimo metu. Virtualus reiškia laukimą iki vykdymo laiko, o eilutę reiškia kompiliavimo metu, jei kompiliatorius nežino, kuri funkcija bus iškviesta, kaip jis gali atlikti įtraukimą? Dar vienas dalykas, kurį reikia atsiminti, yra tai, kad funkciją įtraukti į eilutę naudinga tik tuo atveju, jei funkcijos iškvietimo laikas yra daugiau, palyginti su funkcijos korpuso vykdymo laiku.

Pavyzdys, kai eilutinė funkcija neturi jokio poveikio:

inline void show() { cout << 'value of S = ' << S << endl; }>

Aukščiau pateiktos funkcijos vykdymas užtrunka gana ilgai. Apskritai, funkcija, kuri atlieka įvesties-išvesties (I/O) operaciją, neturėtų būti apibrėžta kaip tiesioginė, nes ji praleidžia daug laiko. Techniškai funkcijos show() įtraukimas yra ribotos vertės, nes laikas, per kurį įvesties/išvesties sakinys užtruks, gerokai viršija funkcijos iškvietimo išlaidas. Priklausomai nuo naudojamo kompiliatoriaus, kompiliatorius gali parodyti įspėjimą, jei funkcija nėra išplėsta.

Tokios programavimo kalbos kaip Java ir C# nepalaiko įterptųjų funkcijų. Tačiau „Java“ versijoje kompiliatorius gali atlikti įtraukimą, kai iškviečiamas mažasis galutinis metodas, nes galutinių metodų negali nepaisyti poklasiai, o galutinio metodo iškvietimas išsprendžiamas kompiliavimo metu.

C# JIT kompiliatorius taip pat gali optimizuoti kodą įtraukdamas mažus funkcijų iškvietimus (pvz., pakeisdamas mažos funkcijos turinį, kai ji iškviečiama cikle). Paskutinis dalykas, kurį reikia nepamiršti, yra tai, kad įterptosios funkcijos yra vertinga C++ savybė. Tinkamas įterptųjų funkcijų naudojimas gali pagerinti našumą, tačiau jei įterptosios funkcijos naudojamos savavališkai, jos negali užtikrinti geresnių rezultatų. Kitaip tariant, nesitikėkite geresnio programos veikimo. Neįtraukite visų funkcijų. Geriau, kad įterptosios funkcijos būtų kuo mažesnės.