Domanda

Se si definisce una funzione membro all'interno della definizione della classe stessa, è necessariamente trattata in linea o è solo una richiesta al compilatore quale può ignorare.

È stato utile?

Soluzione

Sì, funzioni che sono definite all'interno di un corpo di classe sono implicitamente inline.

(Come per le altre funzioni inline dichiarate non vuol dire che il compilatore è chiamato a svolgere l'espansione inline in luoghi in cui viene chiamata la funzione, semplicemente permette ai rilassamenti consentite della "una regola definizione", combinato con il requisito che una definizione deve essere incluso in tutte le unità di traduzione in cui viene utilizzata la funzione.)

Altri suggerimenti

Come già detto da altri, un metodo definito all'interno di una classe viene richiesto automaticamente in linea. E 'utile per capire il perché.

Supponiamo che non lo erano. Avresti per generare il codice per tale funzione, e ovunque si chiama, un salto all'istruzione subroutine avrebbe dovuto fare riferimento alla posizione, tramite il linker.

class A {
public:
  void f() { ... your code ... }
};

Ogni volta che questo codice è visto, se non è in linea, il compilatore può solo supporre che deve essere generato, in modo che genererebbe un simbolo. Supponiamo che era come questo:

A__f_v:

Se quel simbolo fosse globale, quindi se ti è capitato di includere questo codice di classe più volte in diversi moduli, si avrebbe un errore di simbolo definito più volte in fase di collegamento. Quindi non può essere globale. Invece, è un file locale.

Immaginate di includere il file di intestazione di cui sopra in una serie di moduli. In ciascuno di essi, sta andando a generare una copia locale di tale codice. Che è meglio che non la compilazione a tutti, ma che stai ricevendo più copie del codice quando si ha realmente bisogno di un solo.

Questo porta alla seguente conclusione: se il compilatore non ha intenzione di inline una funzione, si sono notevolmente meglio dichiarando da qualche parte una volta, e non richiedendo di essere inline

.

Purtroppo, ciò che è e non è in linea non è portabile. E 'definita dallo scrittore compilatore. Una buona regola è quella di rendere sempre ogni uno di linea, in particolare tutte le funzioni che si basta chiamare una funzione, in linea, come si rimuove in testa. Nulla al di sotto tre righe di codice lineare è quasi certamente ok. Ma se si dispone di un ciclo nel codice, la questione è se il compilatore lo permetterà in linea, e più precisamente, quanto beneficio si dovrebbe vedere anche se lo facesse ciò che si desidera.

considerare questo codice inline:

inline int add(int a, int b) { return a + b; }

Non è solo quasi piccolo come il prototipo sarebbe in codice sorgente, ma il linguaggio assembly generato dal codice inline è più piccola la chiamata a una routine sarebbe. Quindi questo codice è più piccolo e più veloce.

E, se vi capita di essere di passaggio in costanti:

int c= add(5,4);

E 'risolto in fase di compilazione e non v'è alcun codice.

In gcc, di recente ho notato che, anche se lo faccio codice non in linea, se si tratta di locali in un file, saranno subdolamente inline comunque. E 'solo se dichiaro la funzione in un modulo sorgente separata che non ottimizzano via la chiamata.

D'altra estremità dello spettro, si supponga di richiedere in linea su un pezzo 1000 riga di codice. Anche se il vostro compilatore è abbastanza sciocco per andare insieme con essa, l'unica cosa che si salva è la chiamata stessa, e il costo è che ogni volta che si voglia chiamare, il compilatore deve incollare tutto ciò che il codice in. Se si chiama che i tempi di codice n , il codice cresce la dimensione della routine * n. Quindi, qualcosa di più grande di 10 righe è praticamente non vale la pena inlining, fatta eccezione per il caso particolare in cui viene chiamato solo un numero molto limitato di volte. Un esempio di ciò potrebbe essere in un metodo privato chiamato da solo 2 altri.

Se si richiede ad un metodo inline che contiene un ciclo, ha senso solo se si esegue spesso un piccolo numero di volte. Ma prendere in considerazione un ciclo che itera un milione di volte. Anche se il codice è inline, la percentuale di tempo trascorso nella chiamata è molto piccolo. Quindi, se avete i metodi con i cicli in esso, che tendono ad essere più grande in ogni caso, quelli sono la pena di rimuovere dal file di intestazione perché a) tenderanno a essere respinto in quanto in linea dal compilatore e b) anche se sono stati inline, sono generalmente non andando a fornire alcun beneficio

Si è necessariamente trattata dal compilatore come una richiesta di linea - che si può ignorare. Ci sono alcuni modi di dire per definire alcune funzioni nell'intestazione (ad esempio distruttori virtuali vuoto) e alcune definizioni necessarie intestazione (funzioni template), ma diverso da quello vedere GotW # 33 per ulteriori informazioni.

Alcuni hanno notato che il compilatore può anche funzioni inline non hai mai chiesto a, ma non sono sicuro se questo sarebbe vanificato l'obiettivo di richiedere inline una funzione.

Si è infatti inline -. Ma ogni richiesta in linea può essere ignorato dal compilatore

Si tratta di una richiesta al compilatore che si può ignorare.

La norma ISO 2003 C ++ dice

  

7.1.2 / 2 A dichiarazione di funzione (8.3.5, 9.3, 11.4) con un inline   identificatore dichiara un inline   funzione. L'identificatore inline   indica che l'attuazione   sostituzione in linea della funzione   corpo al punto di chiamata deve essere   ha preferito la solita funzione di chiamata
  meccanismo. Un'implementazione non è   necessari per eseguire la linea
  sostituzione al punto di chiamata;   Tuttavia, anche se questo in linea
  sostituzione viene omesso, l'altra   regole per funzioni inline definite   da 7.1.2 devono ancora essere rispettati.

     

7.1.2 / 3 una funzione definita all'interno di una definizione di classe è un inline
  funzione. L'identificatore inline deve   non apparire su un blocco funzionale portata   dichiarazione.

     

7.1.2 / 4 una funzione inline è definita in ogni unità di traduzione in
  quale è utilizzato e deve avere   esattamente la stessa definizione in ogni
  caso (3.2). [Nota: una chiamata alla   funzione inline possono incontrare
  prima della sua defi-nizione appare nella   unità di traduzione. ] Se una funzione   con collegamento esterno è dichiarata   inline in una sola unità TRADUCE-zione, si   sono dichiarati in linea in tutte le   unità di traduzione in cui   appare; non è richiesto diagnostica. Un   Funzione linea con esterna   linkage deve avere lo stesso indirizzo   tutte le unità di traduzione. A statica   variabile locale in un
linea extern   funzione si riferisce sempre alla stessa   oggetto. Una stringa letterale in un
  funzione inline extern è uguale   oggetto in diverse traduzioni
  unità.

Ci sono due cose che non dovrebbero essere ammassati insieme:

  1. Come si contrassegna una funzione come inline: definire con linea di fronte alla firma o definirla al punto di dichiarazione;
  2. Che il compilatore tratterà tale linea di marcatura:. Indipendentemente da come si segna la funzione inline sarà trattata come una richiesta da parte del compilatore
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top