logo

Funcții inline în C++

C++ oferă funcții inline pentru a reduce supraîncărcarea apelurilor de funcție. O funcție inline este o funcție care este extinsă în linie atunci când este apelată. Când funcția inline este numită, întregul cod al funcției inline este inserat sau înlocuit în punctul apelului funcției inline. Această înlocuire este efectuată de compilatorul C++ în timpul compilării. O funcție în linie poate crește eficiența dacă este mică.

Sintaxă:

inline return-type function-name(parameters) { // function code }>
Funcție inline în c++

Amintiți-vă, integrarea este doar o solicitare către compilator, nu o comandă. Compilatorul poate ignora cererea de inline.



Compilatorul nu poate efectua inlineing în astfel de circumstanțe precum:

  1. Dacă o funcție conține o buclă. ( for, while și do-while )
  2. Dacă o funcție conține variabile statice.
  3. Dacă o funcție este recursivă.
  4. Dacă un tip de returnare a funcției este altul decât void, iar instrucțiunea return nu există într-un corp de funcție.
  5. Dacă o funcție conține o instrucțiune switch sau goto.

De ce sunt folosite funcțiile inline?

Când programul execută instrucțiunea de apelare a funcției, CPU stochează adresa de memorie a instrucțiunii care urmează apelului funcției, copiează argumentele funcției pe stivă și în final transferă controlul către funcția specificată. CPU-ul execută apoi codul funcției, stochează valoarea returnată a funcției într-o locație/registru de memorie predefinit și returnează controlul funcției de apelare. Acest lucru poate deveni overhead dacă timpul de execuție al funcției este mai mic decât timpul de comutare de la funcția apelant la funcția apelată (apelată).

Pentru funcțiile care sunt mari și/sau îndeplinesc sarcini complexe, supraîncărcarea apelului de funcție este de obicei nesemnificativă în comparație cu durata de rulare a funcției. Cu toate acestea, pentru funcțiile mici, utilizate în mod obișnuit, timpul necesar pentru a efectua apelul funcției este adesea mult mai mare decât timpul necesar pentru a executa efectiv codul funcției. Această suprasarcină apare pentru funcții mici, deoarece timpul de execuție al unei funcții mici este mai mic decât timpul de comutare.

Funcții în linie Avantaje:

  1. Apelul de funcție nu are loc.
  2. De asemenea, salvează suprasarcina variabilelor push/pop de pe stivă atunci când este apelată o funcție.
  3. De asemenea, salvează costul general al unui apel de retur de la o funcție.
  4. Când introduceți o funcție, puteți activa compilatorul să efectueze optimizarea specifică contextului pe corpul funcției. Astfel de optimizări nu sunt posibile pentru apelurile de funcții normale. Alte optimizări pot fi obținute luând în considerare fluxurile contextului apelant și contextul apelat.
  5. O funcție inline poate fi utilă (dacă este mică) pentru sistemele încorporate, deoarece inline poate produce mai puțin cod decât funcția numită preambul și returnare.

Funcția inline Dezavantaje:

  1. Variabilele adăugate din funcția înliniată consumă registre suplimentare. După funcția de linie în linie, dacă numărul variabilei care va folosi registrul crește, atunci acestea pot crea supraîncărcare pentru utilizarea resurselor variabilei de registru. Aceasta înseamnă că atunci când corpul funcției inline este înlocuit în punctul apelului funcției, este inserat și numărul total de variabile utilizate de funcție. Deci numărul de registre care vor fi utilizate pentru variabile va crește și el. Deci, dacă după funcție, numerele variabile de inline cresc drastic, atunci cu siguranță ar cauza supraîncărcare pentru utilizarea registrului.
  2. Dacă utilizați prea multe funcții inline, atunci dimensiunea fișierului executabil binar va fi mare, din cauza dublării aceluiași cod.
  3. Prea multă introducere poate reduce, de asemenea, rata de accesare a cache-ului de instrucțiuni, reducând astfel viteza de preluare a instrucțiunilor de la cea a memoriei cache la cea a memoriei primare.
  4. Funcția inline poate crește timpul de compilare dacă cineva modifică codul în interiorul funcției inline, atunci toată locația de apelare trebuie să fie recompilată deoarece compilatorul ar trebui să înlocuiască tot codul încă o dată pentru a reflecta modificările, altfel va continua cu vechiul funcţionalitate.
  5. Funcțiile inline pot să nu fie utile pentru multe sisteme încorporate. Pentru că în sistemele încorporate dimensiunea codului este mai importantă decât viteza.
  6. Funcțiile inline pot provoca thrashing, deoarece inline-ul poate crește dimensiunea fișierului executabil binar. Deplasarea în memorie duce la degradarea performanței computerului. Următorul program demonstrează utilizarea funcției inline.

Exemplu:

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

>

>

Ieșire

The cube of 3 is: 27>

Funcție și clase inline

De asemenea, este posibilă definirea funcției inline în interiorul clasei. De fapt, toate funcțiile definite în interiorul clasei sunt implicit inline. Astfel, toate restricțiile funcțiilor inline sunt aplicate și aici. Dacă trebuie să declarați în mod explicit o funcție inline în clasă, atunci declarați funcția în interiorul clasei și definiți-o în afara clasei folosind cuvântul cheie inline.

Sintaxă:

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

Stilul de mai sus este considerat un stil de programare prost. Cel mai bun stil de programare este să scrieți prototipul funcției în interiorul clasei și să îl specificați ca o linie în definiția funcției.

De exemplu:

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

Exemplu:

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

>

sincronizarea firelor
>

Ieșire:

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>

Ce este în neregulă cu macro?

Cititorii familiarizați cu limbajul C știu că limbajul C folosește macro. Preprocesorul înlocuiește toate apelurile macro direct în codul macro. Este recomandat să folosiți întotdeauna funcția inline în loc de macro. Potrivit Dr. Bjarne Stroustrup, creatorul macrocomenzilor C++ nu sunt aproape niciodată necesare în C++ și sunt predispuse la erori. Există unele probleme cu utilizarea macrocomenzilor în C++. Macro nu poate accesa membrii privați ai clasei. Macro-urile arată ca apeluri de funcții, dar de fapt nu sunt.

Exemplu:

C++




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

>

>

Ieșire:

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

Compilatorul C++ verifică tipurile de argument ale funcțiilor inline și conversiile necesare sunt efectuate corect. Macro-ul preprocesorului nu este capabil să facă acest lucru. Un alt lucru este că macrocomenzile sunt gestionate de preprocesor, iar funcțiile inline sunt gestionate de compilatorul C++. Rețineți: este adevărat că toate funcțiile definite în interiorul clasei sunt implicit inline și compilatorul C++ va efectua apeluri inline ale acestor funcții, dar compilatorul C++ nu poate efectua inline dacă funcția este virtuală. Motivul pentru care este apelată o funcție virtuală este rezolvată în timpul execuției, nu în timpul compilării. Virtual înseamnă așteptarea până la runtime și inline înseamnă în timpul compilării, dacă compilatorul nu știe ce funcție va fi apelată, cum poate efectua inlining? Un alt lucru de reținut este că este util să faceți funcția în linie doar dacă timpul petrecut în timpul unui apel de funcție este mai mult în comparație cu timpul de execuție a corpului funcției.

Un exemplu în care funcția inline nu are niciun efect:

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

Funcția de mai sus durează relativ mult timp pentru a se executa. În general, o funcție care efectuează o operație de intrare-ieșire (I/O) nu ar trebui definită ca fiind inline, deoarece petrece o cantitate considerabilă de timp. Din punct de vedere tehnic, integrarea funcției show() are o valoare limitată, deoarece timpul pe care o va dura instrucțiunea I/O depășește cu mult supraîncărcarea unui apel de funcție. În funcție de compilatorul pe care îl utilizați, compilatorul vă poate afișa un avertisment dacă funcția nu este extinsă în linie.

Limbajele de programare precum Java și C# nu acceptă funcții inline. Dar în Java, compilatorul poate efectua inline atunci când este apelată metoda finală mică, deoarece metodele finale nu pot fi suprascrise de subclase, iar apelul la o metodă finală este rezolvat în timpul compilării.

În C#, compilatorul JIT poate optimiza codul prin introducerea de apeluri de funcții mici (cum ar fi înlocuirea corpului unei funcții mici atunci când este apelată într-o buclă). Ultimul lucru de reținut este că funcțiile inline sunt o caracteristică valoroasă a C++. Utilizarea adecvată a funcțiilor inline poate oferi o îmbunătățire a performanței, dar dacă funcțiile inline sunt utilizate în mod arbitrar, atunci nu pot oferi rezultate mai bune. Cu alte cuvinte, nu vă așteptați la o performanță mai bună a programului. Nu faceți fiecare funcție în linie. Este mai bine să păstrați funcțiile inline cât mai mici posibil.