logo

Iekļautās funkcijas programmā C++

C++ nodrošina iekļautas funkcijas, lai samazinātu funkciju izsaukuma izmaksas. Iekļautā funkcija ir funkcija, kas tiek izvērsta rindā, kad tā tiek izsaukta. Kad tiek izsaukta iekļautā funkcija, iekļautās funkcijas izsaukuma vietā tiek ievietots vai aizstāts viss iekļautās funkcijas kods. Šo aizstāšanu kompilēšanas laikā veic C++ kompilators. Iekļautā funkcija var palielināt efektivitāti, ja tā ir maza.

Sintakse:

inline return-type function-name(parameters) { // function code }>
Iekļautā funkcija c++

Atcerieties, ka iekļaušana ir tikai pieprasījums kompilatoram, nevis komanda. Kompilators var ignorēt iekļaušanas pieprasījumu.



Kompilators nedrīkst veikt iekļaušanu šādos apstākļos:

  1. Ja funkcija satur cilpu. ( par, kamēr un darīt-kamēr )
  2. Ja funkcija satur statiskus mainīgos.
  3. Ja funkcija ir rekursīva.
  4. Ja funkcijas atgriešanas veids nav spēkā esošs un atgriešanas priekšraksts neeksistē funkcijas pamattekstā.
  5. Ja funkcija satur slēdzi vai goto paziņojumu.

Kāpēc tiek izmantotas iekļautās funkcijas?

Kad programma izpilda funkcijas izsaukšanas instrukciju, CPU saglabā tās instrukcijas atmiņas adresi, kas seko funkcijas izsaukumam, kopē funkcijas argumentus stekā un visbeidzot nodod vadību norādītajai funkcijai. Pēc tam centrālais procesors izpilda funkcijas kodu, saglabā funkcijas atgriešanas vērtību iepriekš noteiktā atmiņas vietā/reģistrā un atgriež vadību izsaucējai funkcijai. Tas var kļūt par papildu izmaksām, ja funkcijas izpildes laiks ir mazāks par pārslēgšanās laiku no zvanītāja funkcijas uz izsaukto funkciju (callee).

Funkcijām, kas ir lielas un/vai veic sarežģītus uzdevumus, funkcijas izsaukuma pieskaitāmās izmaksas parasti ir nenozīmīgas, salīdzinot ar laiku, kas nepieciešams funkcijas izpildei. Tomēr mazām, bieži lietotām funkcijām laiks, kas nepieciešams funkcijas izsaukšanai, bieži vien ir daudz vairāk nekā laiks, kas nepieciešams, lai faktiski izpildītu funkcijas kodu. Šīs pieskaitāmās izmaksas rodas mazām funkcijām, jo ​​mazas funkcijas izpildes laiks ir mazāks par pārslēgšanās laiku.

Iekļautās funkcijas Priekšrocības:

  1. Funkcijas izsaukuma pieskaitāmās izmaksas nenotiek.
  2. Tas arī saglabā stekā esošo push/pop mainīgo lielumu, kad tiek izsaukta funkcija.
  3. Tas arī ietaupa pieskaitāmās izmaksas par atgriešanās zvanu no funkcijas.
  4. Iekļaujot funkciju, varat iespējot kompilatoram, lai funkcijas pamattekstā veiktu kontekstam atbilstošu optimizāciju. Šāda optimizācija nav iespējama parastajiem funkciju izsaukumiem. Citas optimizācijas var iegūt, ņemot vērā izsaukšanas konteksta un izsauktā konteksta plūsmas.
  5. Iekļautā funkcija var būt noderīga (ja tā ir maza) iegultajām sistēmām, jo ​​iekļautā funkcija var iegūt mazāk koda nekā funkcija, ko sauc par preambulu un atgriešanos.

Iekļautās funkcijas trūkumi:

  1. Pievienotie mainīgie no iekļautās funkcijas patērē papildu reģistrus. Pēc iekļautās funkcijas, ja palielinās mainīgo skaits, kas izmantos reģistru, tie var radīt papildu izmaksas par reģistra mainīgā resursu izmantošanu. Tas nozīmē, ka, kad funkcijas izsaukšanas punktā tiek aizstāts iekļautais funkcijas pamatteksts, tiek ievietots arī kopējais funkcijas izmantoto mainīgo lielumu skaits. Tādējādi palielināsies arī mainīgajiem lielumiem izmantojamo reģistru skaits. Tātad, ja pēc funkcijas iekļaušanas mainīgo skaitļi krasi palielinās, tas noteikti radīs pieskaitāmās izmaksas par reģistra izmantošanu.
  2. Ja izmantojat pārāk daudz iekļauto funkciju, binārā izpildāmā faila izmērs būs liels viena un tā paša koda dublēšanās dēļ.
  3. Pārāk daudz iekļaušanas var arī samazināt instrukciju kešatmiņas trāpījumu skaitu, tādējādi samazinot instrukciju ielādes ātrumu no kešatmiņas ātruma uz primārās atmiņas ātrumu.
  4. Iekļautā funkcija var palielināt kompilēšanas laiku, ja kāds maina kodu iekļautajā funkcijā, tad visa izsaucēja vieta ir jāpārkompilē, jo kompilatoram atkal būs jāaizstāj viss kods, lai atspoguļotu izmaiņas, pretējā gadījumā tas turpinās ar veco funkcionalitāte.
  5. Iekļautās funkcijas var nebūt noderīgas daudzām iegultajām sistēmām. Jo iegultās sistēmās koda lielums ir svarīgāks par ātrumu.
  6. Iekļautās funkcijas var izraisīt sagraušanu, jo iekļaušana var palielināt binārā izpildāmā faila lielumu. Sagraušana atmiņā izraisa datora veiktspējas pasliktināšanos. Šī programma parāda iekļautās funkcijas izmantošanu.

Piemērs:

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

>

>

Izvade

The cube of 3 is: 27>

Iekļautā funkcija un klases

Klasē ir iespējams arī definēt iekļauto funkciju. Faktiski visas klasē definētās funkcijas ir netieši iekļautas. Tādējādi šeit tiek piemēroti arī visi iekļauto funkciju ierobežojumi. Ja klasē ir skaidri jādeklarē iekļauta funkcija, vienkārši deklarējiet funkciju klasē un definējiet to ārpus klases, izmantojot iekļauto atslēgvārdu.

Sintakse:

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

Iepriekš minētais stils tiek uzskatīts par sliktu programmēšanas stilu. Labākais programmēšanas stils ir vienkārši ierakstīt funkcijas prototipu klasē un norādīt to kā iekļautu funkcijas definīcijā.

Piemēram:

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

Piemērs:

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

>

apļa plānošanas algoritms
>

Izvade:

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 ir nepareizi ar makro?

Lasītāji, kas pārzina C valodu, zina, ka C valoda izmanto makro. Priekšprocesors aizstāj visus makro izsaukumus tieši makro kodā. Ieteicams vienmēr izmantot iekļauto funkciju, nevis makro. Saskaņā ar Dr. Bjarne Stroustrup teikto, C++ makro veidotājs C++ valodā gandrīz nekad nav nepieciešams, un tie ir pakļauti kļūdām. Ir dažas problēmas, izmantojot makro C++. Makro nevar piekļūt privātajiem klases dalībniekiem. Makro izskatās kā funkciju izsaukumi, bet patiesībā tā nav.

Piemērs:

C++




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

>

>

Izvade:

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

C++ kompilators pārbauda iekļauto funkciju argumentu tipus un pareizi tiek veiktas nepieciešamās konvertācijas. Priekšprocesora makro to nevar izdarīt. Vēl viena lieta ir tāda, ka makro pārvalda priekšprocesors, bet iekļautās funkcijas pārvalda C++ kompilators. Atcerieties: tā ir taisnība, ka visas klasē definētās funkcijas ir netieši iekļautas, un C++ kompilators veiks šo funkciju iekļautos izsaukumus, taču C++ kompilators nevar veikt iekļauto funkciju, ja funkcija ir virtuāla. Virtuālās funkcijas izsaukšanas iemesls tiek atrisināts izpildlaikā, nevis kompilēšanas laikā. Virtuālais nozīmē gaidīšanu līdz izpildlaikam un iekļauts nozīmē kompilācijas laikā, ja kompilators nezina, kura funkcija tiks izsaukta, kā tas var veikt iekļaušanu? Vēl viena lieta, kas jāatceras, ir tas, ka ir lietderīgi iekļaut funkciju tikai tad, ja funkcijas izsaukšanas laikā pavadītais laiks ir vairāk salīdzinājumā ar funkcijas korpusa izpildes laiku.

Piemērs, kurā iekļautajai funkcijai nav nekādas ietekmes:

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

Iepriekš minētās funkcijas izpilde aizņem salīdzinoši ilgu laiku. Parasti funkciju, kas veic ievades-izejas (I/O) darbību, nevajadzētu definēt kā iekļautu, jo tā patērē daudz laika. Funkcijas show() tehniski iekļaušanai ir ierobežota vērtība, jo laiks, kas nepieciešams I/O paziņojumam, ievērojami pārsniedz funkcijas izsaukuma izmaksas. Atkarībā no kompilatora, kuru izmantojat, kompilators var parādīt brīdinājumu, ja funkcija nav paplašināta.

Programmēšanas valodas, piemēram, Java un C#, neatbalsta iekļautās funkcijas. Taču Java versijā kompilators var veikt iekļaušanu, kad tiek izsaukta mazā galīgā metode, jo galīgās metodes nevar ignorēt apakšklases, un galīgās metodes izsaukums tiek atrisināts kompilēšanas laikā.

C# versijā JIT kompilators var arī optimizēt kodu, iekļaujot nelielus funkciju izsaukumus (piemēram, mazas funkcijas pamattekstu, kad tā tiek izsaukta cilpā). Pēdējā lieta, kas jāpatur prātā, ir tāda, ka iekļautās funkcijas ir vērtīga C++ iezīme. Pareiza iekļauto funkciju izmantošana var uzlabot veiktspēju, taču, ja iekļautās funkcijas tiek izmantotas patvaļīgi, tās nevar nodrošināt labākus rezultātus. Citiem vārdiem sakot, negaidiet labāku programmas veiktspēju. Neiekļaujiet visas funkcijas. Labāk ir saglabāt iekļautās funkcijas pēc iespējas mazākas.