Inline-functieprototype versus reguliere aangifte versus prototype

Wat is het verschil tussen inline-functie en vervolgens main zoals zo:

inline double cube(double side)
{
   return side * side * side;
}

int main( )
{
    cube(5);
}

vs gewoon een functie regelmatig aangeven, zoals:

double cube(double side)
{
   return side * side * side;
}

int main( )
{
    cube(5);
}

versus functie-prototype?

double cube(double);

int main( )
{
    cube(5);
}

double cube(double side)
{
   return side * side * side;
}
3
mogelijk duplicaat van c ++ inline-functie? - zie ook cf. dit antwoord van mij .
toegevoegd de auteur Kerrek SB, de bron
Bedoelde u cube (5); ?
toegevoegd de auteur log0, de bron
Ik veronderstelde ja.
toegevoegd de auteur log0, de bron

4 antwoord

Een inline -functie kan worden gedefinieerd in meerdere vertaaleenheden (cpp-bestand + inclusief), en is een hint voor de compiler om de functie inline te plaatsen. Het wordt meestal in een header geplaatst die de compileertijd verhoogt, maar kan tot snellere code leiden. Het maakt het ook mogelijk de functie te gebruiken vanuit vele compilatie-eenheden.

//cube.h
inline double cube(double side)
{
   return side * side * side;
}

//cube.cpp
int main( )
{
    cube(5);
}

Regelmatig definiëren is de normale methode, waar deze (meestal) wordt gedefinieerd in een cpp-bestand en wordt gekoppeld aan. Het wordt niet gemakkelijk gebruikt van andere compilatie-eenheden.

//cube.cpp
double cube(double side)
{
   return side * side * side;
}

int main( )
{
    cube(5);
}

Met een prototype kunt u de compiler laten weten dat er een functie bestaat op het moment van koppelen, zelfs als deze nog niet helemaal bestaat. Hierdoor kan main de functie bellen, ook al bestaat deze nog niet. Gewoonlijk bevinden prototypen zich in headers, zodat andere compilatie-eenheden de functie kunnen noemen, zonder deze zelf te definiëren. Dit heeft de snelste compilatietijd en de functie is eenvoudig te gebruiken vanuit andere compilatie-eenheden.

//cube.h
double cube(double);

//cube.cpp
int main( )
{
    cube(5);
}

double cube(double side)
{
   return side * side * side;
}
6
toegevoegd
Uitstekende en zeer begrijpelijke verklaring, mijnheer. Erg bedankt!
toegevoegd de auteur iggy2012, de bron
Het laatste voorbeeld is ongedefinieerd gedrag zonder diagnostische vereiste, als cube.h is opgenomen in zowel cube.cpp als een andere vertaaleenheid. Een functie is mogelijk niet inline in één eenheid en niet-inline in een andere.
toegevoegd de auteur M.M, de bron
In het tweede voorbeeld zou het een goede gewoonte zijn om de functie als interne koppeling te markeren om per ongeluk ongedefinieerd gedrag te voorkomen, in het geval dat een ander deel van het project ook een functie maakt met de naam kubus
toegevoegd de auteur M.M, de bron
... kan meerdere keren worden gedefinieerd in een enkele compilatie-eenheid (cpp-bestand + bevat) - bedoelde u verschillende compilatie-eenheden?
toegevoegd de auteur anatolyg, de bron
@MooingDuck: anatolyg heeft gelijk, een inline -functie kan slechts eenmaal in een vertaaleenheid worden gedefinieerd, zelfs als deze meerdere keren in een programma kan worden gedefinieerd zonder de ODR te schenden.
toegevoegd de auteur David Rodríguez - dribeas, de bron
Nee, inline mag de ODR schenden, zoals sjablonen. Anders zou het moeilijk zijn om een ​​inline in de header te plaatsen, en als het niet in de header stond, konden domme compilers het niet inline zetten!
toegevoegd de auteur Mooing Duck, de bron
Oh goed, ik heb het verkeerd. Vergat de onder andere bewakers.
toegevoegd de auteur Mooing Duck, de bron
@ M.M: De extra inline in het laatste voorbeeld opgelost, bedankt. Je hebt gelijk wat betreft interne koppeling, maar dat is extra complexiteit die niet superrelevant is voor het antwoord.
toegevoegd de auteur Mooing Duck, de bron
Waarom wordt dit niet geaccepteerd als een antwoord dat ik me afvraag.
toegevoegd de auteur Felype, de bron

Prestaties wijs, ze zijn allemaal hetzelfde, omdat inline slechts een hint voor de compiler is. Als de scheiding van declaratie/definitie wordt gebruikt en de definitie zich op een andere vertaaleenheid bevindt, is het voor de compiler moeilijker om deze te inline (maar er zijn implementaties die dit wel doen).

Een verschil met het maken van een functie inline of niet, is dat de linker niet zal klagen als hij dezelfde inline-definitie voor een functie meer dan eens ziet.

1
toegevoegd

Het 3-programma compileert exact hetzelfde met g ++ -S -O3 $ file.cc . Met uitzondering van het tweede voorbeeld waarbij de definitie van dubbele kubus (dubbele zijde) nog steeds bestaat in een niet-gelinieerde vorm hoewel deze is onderstreept in int main() .

_main:
pushl   %ebp
movl    $16, %eax
movl    %esp, %ebp
subl    $8, %esp
andl    $-16, %esp
call    __alloca
call    ___main
leave
xorl    %eax, %eax
ret
1
toegevoegd
Het verschil dat u aangeeft is een detail van de implementatie, sommige compilers genereren altijd alle functies, zelfs als deze feitelijk zijn gestructureerd omdat u het adres van een inline -functie kunt verkrijgen en de compiler mogelijk niet weet tijdens het verwerken van de functie als later in hetzelfde TU-adres van die functie gevraagd zal worden.
toegevoegd de auteur David Rodríguez - dribeas, de bron
@David Precies.
toegevoegd de auteur log0, de bron

Wanneer u een functie inline declareert, probeert de compiler de code te versnellen door de hoofdtekst van de functie min of meer te kopiëren naar waar deze wordt opgeroepen. Het is slechts een suggestie en het is aan de compiler om de beslissing te nemen als het mogelijk is.

Ik weet niet zeker wat er zou gebeuren in het derde voorbeeld. Ik kan me voorstellen dat dit afhangt van de gebruikte gereedschapsketen.

0
toegevoegd
De laatste is slechts een functie-prototype vóór de main (). Ze lijken allemaal op dezelfde manier te werken, maar ik begrijp niet wat het verschil is.
toegevoegd de auteur iggy2012, de bron