Quando dovrei scrivere la parola chiave "inline" per una funzione/metodo?
-
20-09-2019 - |
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?
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:
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!
Linker non si lamenta Una regola di definizione, COME
fun()
è dichiarato comeinline
.Tuttavia, perché inline111.cpp è la prima unità di traduzione (che in realtà chiamafun()
) elaborato dal compilatore, il compilatore crea un'istanzafun()
sul suo Primo incontro di chiamata in inline111.cpp.Se il compilatore decide non espanderefun()
alla sua chiamata da qualsiasi altra parte del programma (per esempio. da inline222.cpp), la chiamata afun()
sarà sempre collegato alla sua istanza prodotta da inline111.cpp (la chiamata afun()
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.Infine, nonostante il
inline
suggerimento al compilatore di effettivamente espandersi la battutafun()
, 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:
Questo caso afferma ciò che è stato discusso in Caso A.
Nota un punto importante, ovvero se commenti la chiamata effettiva a
fun()
In inline222.cpp (per esempio. commentarecout
-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 COMEinline111: 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:
- 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, ilfun()
è stato effettivamente in linea espanso (secondo la sua definizione in questo particolare unità di traduzione), risultando in due diversofun()
stampe.Nonostante questo, c'è ancora solo uno istanza collegata a livello globale difun()
(come previsto dalla norma), come risulta evidente da identico&fun
stampare.
- Come è descritto qui,
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 .