logo

Inline-funktioner i C++

C++ tillhandahåller inline-funktioner för att minska funktionsanropsoverheaden. En inline-funktion är en funktion som utökas i rad när den anropas. När inline-funktionen anropas kommer hela koden för inline-funktionen att infogas eller ersättas vid punkten för inline-funktionsanropet. Denna substitution utförs av C++-kompilatorn vid kompilering. En inline-funktion kan öka effektiviteten om den är liten.

Syntax:



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

Kom ihåg att inlining bara är en begäran till kompilatorn, inte ett kommando. Kompilatorn kan ignorera begäran om inlining.

Kompilatorn får inte utföra inlining under sådana omständigheter som:

  1. Om en funktion innehåller en loop. ( för, medan och gör-under )
  2. Om en funktion innehåller statiska variabler.
  3. Om en funktion är rekursiv.
  4. Om en funktionsreturtyp är annan än void och retursatsen inte finns i en funktionskropp.
  5. Om en funktion innehåller en switch eller goto-sats.

Varför används inline-funktioner?

När programmet kör funktionsanropsinstruktionen lagrar CPU:n minnesadressen för instruktionen efter funktionsanropet, kopierar argumenten för funktionen på stacken och överför slutligen kontrollen till den specificerade funktionen. CPU:n exekverar sedan funktionskoden, lagrar funktionsreturvärdet i en fördefinierad minnesplats/register och återför kontrollen till den anropande funktionen. Detta kan bli overhead om exekveringstiden för funktionen är mindre än växlingstiden från anropsfunktionen till anropad funktion (callee).



För funktioner som är stora och/eller utför komplexa uppgifter är omkostnaden för funktionsanropet vanligtvis obetydlig jämfört med hur lång tid det tar att köra funktionen. Men för små, vanliga funktioner är tiden som krävs för att göra funktionsanropet ofta mycket mer än den tid som behövs för att faktiskt exekvera funktionens kod. Denna overhead uppstår för små funktioner eftersom exekveringstiden för en liten funktion är mindre än kopplingstiden.

Inline funktioner Fördelar:

  1. Funktionsanropsoverhead förekommer inte.
  2. Det sparar också omkostnaden för push/pop-variabler på stacken när en funktion anropas.
  3. Det sparar också omkostnader för ett retursamtal från en funktion.
  4. När du infogar en funktion kan du göra det möjligt för kompilatorn att utföra kontextspecifik optimering av funktionen. Sådana optimeringar är inte möjliga för normala funktionsanrop. Andra optimeringar kan erhållas genom att överväga flödena av anropskontexten och den anropade kontexten.
  5. En inline-funktion kan vara användbar (om den är liten) för inbäddade system eftersom inline kan ge mindre kod än funktionen som kallas preamble and return.

Inline funktion Nackdelar:

  1. De tillagda variablerna från den infogade funktionen förbrukar ytterligare register. Efter inliningfunktionen ökar variabelantalet som kommer att använda registret så kan de skapa overhead på registervariabelresursanvändning. Detta innebär att när den inline-funktionskroppen ersätts vid punkten för funktionsanropet, infogas det totala antalet variabler som används av funktionen. Så antalet register som kommer att användas för variablerna kommer också att öka. Så om efter funktion inlining variabel nummer ökar drastiskt så skulle det säkert orsaka overhead på registeranvändning.
  2. Om du använder för många inline-funktioner kommer storleken på den binära körbara filen att bli stor på grund av dupliceringen av samma kod.
  3. För mycket inlining kan också minska din instruktionscache-träffhastighet, vilket minskar hastigheten för instruktionshämtning från den för cacheminnet till den för primärminnet.
  4. Inline-funktionen kan öka kompileringstiden överhead om någon ändrar koden i den inline-funktionen måste alla anropsplatser kompileras om eftersom kompilatorn skulle behöva ersätta all kod igen för att återspegla ändringarna, annars kommer den att fortsätta med gamla funktionalitet.
  5. Inline-funktioner kanske inte är användbara för många inbyggda system. För i inbyggda system är kodstorlek viktigare än hastighet.
  6. Inline-funktioner kan orsaka thrashing eftersom inlining kan öka storleken på den binära körbara filen. Att slå i minnet gör att datorns prestanda försämras. Följande program visar användningen av inline-funktionen.

Exempel:

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

>

>

Produktion

The cube of 3 is: 27>

Inline funktion och klasser

Det är också möjligt att definiera inline-funktionen inuti klassen. Faktum är att alla funktioner som definieras i klassen är implicit inline. Således tillämpas alla begränsningar för inline-funktioner också här. Om du uttryckligen behöver deklarera en inline-funktion i klassen, deklarera bara funktionen inuti klassen och definiera den utanför klassen med hjälp av inline-nyckelordet.

Syntax:

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

Ovanstående stil anses vara en dålig programmeringsstil. Den bästa programmeringsstilen är att bara skriva prototypen av funktionen inuti klassen och specificera den som en inline i funktionsdefinitionen.

Till exempel:

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

Exempel:

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

>

jsp javatpoint
>

Produktion:

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>

Vad är det för fel på makrot?

Läsare som är bekanta med C-språket vet att C-språket använder makro. Förprocessorn ersätter alla makroanrop direkt inom makrokoden. Det rekommenderas att alltid använda inline-funktionen istället för makrot. Enligt Dr Bjarne Stroustrup är skaparen av C++ makron nästan aldrig nödvändiga i C++ och de är felbenägna. Det finns vissa problem med användningen av makron i C++. Makro kan inte komma åt privata medlemmar i klassen. Makron ser ut som funktionsanrop men det är de faktiskt inte.

Exempel:

C++




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

>

>

Produktion:

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

C++-kompilatorn kontrollerar argumenttyperna för inline-funktioner och nödvändiga omvandlingar utförs korrekt. Förprocessormakrot kan inte göra detta. En annan sak är att makron hanteras av förprocessorn och inline-funktioner hanteras av C++-kompilatorn. Kom ihåg: Det är sant att alla funktioner som definieras i klassen är implicit inline och C++ kompilatorn kommer att utföra inline anrop av dessa funktioner, men C++ kompilatorn kan inte utföra inline om funktionen är virtuell. Anledningen anropas till en virtuell funktion löses vid körning istället för kompileringstid. Virtuell betyder att vänta tills körningstid och inline betyder under kompilering, om kompilatorn inte vet vilken funktion som kommer att anropas, hur kan den utföra inlining? En annan sak att komma ihåg är att det bara är användbart att göra funktionen inline om tiden som spenderas under ett funktionsanrop är mer jämfört med funktionskroppens exekveringstid.

Ett exempel där inline-funktionen inte har någon effekt alls:

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

Ovanstående funktion tar relativt lång tid att utföra. I allmänhet bör en funktion som utför en input-output (I/O) operation inte definieras som inline eftersom den tillbringar en avsevärd tid. Tekniskt sett är inlining av show()-funktionen av begränsat värde eftersom den tid som I/O-satsen tar vida överstiger overheaden för ett funktionsanrop. Beroende på vilken kompilator du använder kan kompilatorn visa dig en varning om funktionen inte expanderas inline.

Programmeringsspråk som Java och C# stöder inte inline-funktioner. Men i Java kan kompilatorn utföra inlining när den lilla slutliga metoden anropas eftersom slutmetoder inte kan åsidosättas av underklasser, och anropet till en slutlig metod löses vid kompilering.

I C# kan JIT-kompilator också optimera kod genom att infoga små funktionsanrop (som att ersätta kroppen av en liten funktion när den anropas i en loop). Det sista att tänka på är att inline-funktioner är en värdefull egenskap hos C++. Lämplig användning av inline-funktioner kan ge prestandaförbättring, men om inline-funktioner används godtyckligt kan de inte ge bättre resultat. Med andra ord, förvänta dig inte ett bättre resultat av programmet. Gör inte alla funktioner inline. Det är bättre att hålla inline-funktionerna så små som möjligt.