Domanda

Quando dovrei scrivere la parola chiave inline per una funzione/metodo in C++?

Dopo aver visto alcune risposte, alcune domande correlate:

  • Quando dovrei non scrivere la parola chiave "inline" per una funzione/metodo in C++?

  • Quando il compilatore non saprà quando rendere una funzione/metodo "inline"?

  • Importa se un'applicazione lo è multithread quando si scrive "inline" per una funzione/metodo?

È stato utile?

Soluzione

Oh uomo, uno dei miei fastidi ricorrenti.

inline è più simile static o extern di una direttiva dice al compilatore di inline le funzioni. extern, static, inline sono direttive linkage, utilizzati quasi esclusivamente dal linker, non il compilatore.

Si dice che i suggerimenti inline al compilatore che si pensa la funzione deve essere inline. Che potrebbe essere stato vero nel 1998, ma un decennio più tardi il compilatore non ha bisogno di questi suggerimenti. Per non parlare gli esseri umani sono di solito sbagliato quando si tratta di ottimizzare il codice, quindi la maggior parte dei compilatori flat out ignorano il 'suggerimento'.

  • static - il nome / funzione di variabile non può essere utilizzato in altre unità di traduzione. Linker deve assicurarsi che non utilizza accidentalmente una variabile / funzione definita staticamente da un'altra unità di traduzione.

  • extern - utilizzare questo nome / funzione di variabili in questa unità di traduzione, ma non lamentatevi se non è definito. Il linker risolvere il problema e assicurarsi che tutto il codice che ha cercato di usare un po 'il simbolo extern ha il suo indirizzo.

  • inline - questa funzione sarà definito in più unità di traduzione, non ti preoccupare. Il linker ha bisogno per assicurarsi che tutte le unità di traduzione utilizzano una singola istanza del / funzione variabile.

Nota: In generale, dichiarando modelli inline è inutile, in quanto hanno la semantica di collegamento di inline già. Tuttavia, specializzazione esplicita e di istanze di modelli richiedono inline da utilizzare.


risposte specifiche alle tue domande:

  •   

    Quando devo scrivere la parola 'inline' per una funzione / metodo in C ++?

    Solo quando si desidera che la funzione da definire in un colpo di testa. Più esattamente solo quando la definizione della funzione può presentarsi in più unità di traduzione. E 'una buona idea quella di definire le funzioni di piccole dimensioni (come in uno di linea) nel file di intestazione in quanto dà al compilatore maggiori informazioni per lavorare con mentre l'ottimizzazione del codice. Aumenta anche il tempo di compilazione.

  •   

    Quando non dovrei scrivere la parola 'inline' per una funzione / metodo in C ++?

    Non aggiungere in linea solo perché pensate che il vostro codice verrà eseguito più velocemente se il compilatore inline esso.

  •   

    Quando sarà il compilatore non sapere quando fare una funzione / metodo di 'inline'?

    In generale, il compilatore sarà in grado di fare questo meglio di te. Tuttavia, il compilatore non ha la possibilità di inline codice, se non ha la definizione della funzione. Nel codice di massimo ottimizzato di solito tutti i metodi private sono inline se chiedete o no.

    Per inciso per prevenire inlining in GCC, uso __attribute__(( noinline )), e in Visual Studio, l'uso __declspec(noinline).

  •   

    Che importa se un'applicazione è multithread quando si scrive 'inline' per una funzione / metodo?

    Il multithreading non influisce inlining in alcun modo.

Altri suggerimenti

Vorrei contribuire a tutte le ottime risposte in questo thread con un esempio convincente per dissipare eventuali malintesi rimanenti.

Dati due file sorgente, come ad esempio:

  • inline111.cpp:

    #include <iostream>
    
    void bar();
    
    inline int fun() {
      return 111;
    }
    
    int main() {
      std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun;
      bar();
    }
    
  • inline222.cpp:

    #include <iostream>
    
    inline int fun() {
      return 222;
    }
    
    void bar() {
      std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun;
    }
    

  • Caso A:

    Compilare:

    g++ -std=c++11 inline111.cpp inline222.cpp
    

    Produzione:

    inline111: fun() = 111, &fun = 0x4029a0
    inline222: fun() = 111, &fun = 0x4029a0
    

    Discussione:

    1. Anche tu dovresti avere definizioni identiche delle tue funzioni in linea, il compilatore C ++ non lo segnala se non è così (in realtà, a causa di compilazione separata non ha modo di verificarlo).È tuo dovere garantire questo!

    2. Linker non si lamenta Una regola di definizione, COME fun() è dichiarato come inline.Tuttavia, perché inline111.cpp è la prima unità di traduzione (che in realtà chiama fun()) elaborato dal compilatore, il compilatore crea un'istanza fun() sul suo Primo incontro di chiamata in inline111.cpp.Se il compilatore decide non espandere fun() alla sua chiamata da qualsiasi altra parte del programma (per esempio. da inline222.cpp), la chiamata a fun() sarà sempre collegato alla sua istanza prodotta da inline111.cpp (la chiamata a fun() dentro inline222.cpp potrebbe anche produrre un'istanza in quell'unità di traduzione, ma rimarrà scollegata).In effetti, questo è evidente dallo stesso &fun = 0x4029a0 stampe.

    3. Infine, nonostante il inline suggerimento al compilatore di effettivamente espandersi la battuta fun(), Esso ignora il tuo suggerimento completamente, il che è chiaro perché fun() = 111 in entrambe le righe.


  • Caso B:

    Compilare (attenzione all'ordine inverso):

    g++ -std=c++11 inline222.cpp inline111.cpp
    

    Produzione:

    inline111: fun() = 222, &fun = 0x402980
    inline222: fun() = 222, &fun = 0x402980
    

    Discussione:

    1. Questo caso afferma ciò che è stato discusso in Caso A.

    2. Nota un punto importante, ovvero se commenti la chiamata effettiva a fun() In inline222.cpp (per esempio. commentare cout-dichiarazione in inline222.cpp completamente) quindi, nonostante l'ordine di compilazione delle unità di traduzione, fun() verrà istanziato al primo incontro di chiamata inline111.cpp, con conseguente stampa per Caso B COME inline111: fun() = 111, &fun = 0x402980.


  • Caso C:

    Compilare (avviso -O2):

    g++ -std=c++11 -O2 inline222.cpp inline111.cpp
    

    O

    g++ -std=c++11 -O2 inline111.cpp inline222.cpp
    

    Produzione:

    inline111: fun() = 111, &fun = 0x402900
    inline222: fun() = 222, &fun = 0x402900
    

    Discussione:

    1. Come è descritto qui, -O2 l'ottimizzazione incoraggia il compilatore a effettivamente espandersi le funzioni che possono essere inline (notare anche che -fno-inline È predefinito senza opzioni di ottimizzazione).Come è evidente dalla stampa qui, il fun() è stato effettivamente in linea espanso (secondo la sua definizione in questo particolare unità di traduzione), risultando in due diverso fun() stampe.Nonostante questo, c'è ancora solo uno istanza collegata a livello globale di fun() (come previsto dalla norma), come risulta evidente da identico &fun stampare.

Hai ancora bisogno di inline in modo esplicito la funzione quando si fa modello di specializzazione (se la specializzazione è nel file h)

1) Al giorno d'oggi, praticamente mai. Se si tratta di una buona idea per inline una funzione, il compilatore lo farà senza il tuo aiuto.

2) Sempre. Vedere 1 #.

(A cura di riflettere sul fatto che hai rotto la tua domanda in due domande ...)

  

Quando non dovrei scrivere la parola 'inline' per una funzione / metodo in C ++?

Se la funzione è definita nel file .cpp, si dovrebbe non scrivere la parola chiave.

  

Quando verrà il il compilatore non sapere quando fare una funzione / metodo di 'inline'?

Non esiste una situazione. Il compilatore non può fare una funzione inline. Tutto ciò che può fare è di inline alcune o tutte le chiamate alla funzione. Non può farlo se non ha il codice della funzione (in questo caso il linker deve fare se è in grado di farlo).

  

Che importa se un'applicazione è multithread quando si scrive 'inline' per una funzione / metodo?

No, questo non importa affatto.

  • Quando verrà il il compilatore non sapere quando fare una funzione / metodo di 'inline'?

Questo dipende dal compilatore utilizzato. Non si fidano ciecamente che al giorno d'oggi i compilatori sanno meglio allora gli esseri umani come in linea e non si dovrebbe mai usare per motivi di prestazioni, perché è di direttiva legame piuttosto che l'ottimizzazione suggerimento. Mentre sono d'accordo che ideologicamente sono questi argomenti corretti incontrando la realtà potrebbe essere una cosa diversa.

Dopo aver letto più thread in giro ho provato per curiosità gli effetti della linea sul codice sto solo di lavoro ed i risultati sono stati che ho ottenuto aumento di velocità misurabile per GCC e senza velocità per Intel compilatore.

(Più particolare: simulazioni matematiche con alcune funzioni critiche definite fuori classe, GCC 4.6.3 (g ++ -O3), ICC 13.1.0 (-O3 ICPC); aggiungendo ancorato a punti critici causato speedup + 6% con il codice GCC ).

Quindi, se si qualificano GCC 4.6 come compilatore moderna il risultato è che la direttiva in linea è ancora importante se si scrive attività ad alta intensità di CPU e sapere dove si trova esattamente il collo di bottiglia.

In realtà, praticamente mai. Tutto quello che stai facendo è suggerendo che il compilatore fanno una funzione data in linea (ad esempio, sostituire tutte le chiamate a questa funzione / w suo corpo). Non ci sono garanzie, ovviamente: il compilatore può ignorare la direttiva

.

Il compilatore generalmente fare un buon lavoro di rilevare le cose + ottimizzando come questa.

  

gcc di default non inline alcuna funzione durante la compilazione senza   ottimizzazione abilitato. Non so su Visual Studio - deft_code

ho controllato questo per Visual Studio 9 (15.00.30729.01) per la compilazione con / FACS e guardando il codice assembly: Il compilatore ha prodotto le chiamate a funzioni membro senza ottimizzazione abilitata in modalità di debug. Anche se la funzione è contrassegnato con __ forceinline , viene prodotto nessun codice inline fase di esecuzione.

Si vuole mettere in fin dall'inizio, prima che tipo di ritorno. Ma la maggior parte compilatori ignorano. Se è definita, e ha un blocco più piccolo di codice, la maggior parte dei compilatori considerano inline comunque.

Quando lo sviluppo e il debug del codice, lasciare inline fuori. Si complica il debug.

Il motivo principale per l'aggiunta di loro è quello di ottimizzare il codice generato. In genere questo contratti è cresciuta spazio di codice per la velocità, ma a volte inline consente di risparmiare spazio di codice e l'esecuzione di tempo.

Spendendo questo tipo di pensiero circa l'ottimizzazione delle prestazioni prima del completamento algoritmo è ottimizzazione prematura .

Quando si dovrebbe inline:

1. Quando uno vuole evitare sovraccarico di cose che accadono quando la funzione viene chiamata come passaggio di parametri, il trasferimento di controllo, il ritorno di controllo ecc.

funzione 2.The dovrebbe essere piccolo, spesso chiamato e facendo in linea è davvero vantaggiosa in quanto come da regola 80-20, cercare di rendere quelli funzione inline dotato di un notevole impatto sulle prestazioni del programma.

Come sappiamo che in linea è solo una richiesta a compilatore simile a registrarsi e vi costerà alla dimensione del codice oggetto.

A meno che non si sta scrivendo una libreria o hanno motivi particolari, si può dimenticare inline e usare ottimizzazione dei link-time , invece. Si elimina la necessità che una definizione funzione deve essere in un'intestazione per essere considerato per inlining attraverso unità di compilazione, che è appunto quello inline consente.

(Ma vedi C'è qualche ragione perché non utilizzare l'ottimizzazione dei tempi di collegamento? )

C ++ inline funzione è potente concetto che viene comunemente utilizzato con le classi. Se una funzione è inline, il compilatore inserisce una copia del codice di tale funzione in ogni punto in cui la funzione è chiamata al momento della compilazione.

Qualsiasi modifica di una funzione inline potrebbe richiedere tutti i clienti della funzione essere ricompilato perché compilatore avrebbe bisogno di sostituire tutto il codice ancora una volta altrimenti continuerà con la vecchia funzionalità.

Per inline una funzione, inserire la parola chiave inline prima che il nome della funzione e definire la funzione prima delle chiamate sono fatte per la funzione. Il compilatore può ignorare la qualificazione ancorato in funzione definita caso è più di una riga.

Una definizione di funzione in una definizione di classe è una definizione funzione inline, anche senza l'uso del specificatore linea.

seguente è un esempio, che fa uso di funzione inline per restituire massimo di due numeri

#include <iostream>

using namespace std;

inline int Max(int x, int y) { return (x > y)? x : y; }

// Main function for the program
int main() {
   cout << "Max (100,1010): " << Max(100,1010) << endl;

   return 0;
}

Per ulteriori informazioni, vedere qui .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top