Qual è il metodo di inlining?

Ho cercato di capire cosa significhi realmente:

funzione inline

In C ++, una funzione membro definita nella dichiarazione della class. (2) Una chiamata di funzione che il compilatore sostituisce con il codice effettivo per la funzione. La parola chiave inline può essere utilizzata per suggerire al compilatore di eseguire l’espansione in linea del corpo di una funzione membro o non membro.

in linea

Per sostituire una chiamata di funzione con una copia del codice della funzione durante la compilazione.

Ad esempio è scritto qualcosa come:

Quando un metodo è definitivo, potrebbe essere in linea.

Qui: http://www.roseindia.net/javatutorials/final_methods.shtml

Puoi darmi un esempio o qualcosa o fondamentalmente aiutarmi a capire cosa significa “potrebbe essere inline”.

Grazie.

Inlining è un’ottimizzazione eseguita dal compilatore Java Just-In-Time.

Se hai un metodo:

public int addPlusOne(int a, int b) { return a + b + 1; } 

che chiami così:

 public void testAddPlusOne() { int v1 = addPlusOne(2, 5); int v2 = addPlusOne(7, 13); // do something with v1, v2 } 

il compilatore può decidere di sostituire la chiamata di funzione con il corpo della funzione, quindi il risultato sarebbe effettivamente simile a questo:

 public void testAddPlusOne() { int v1 = 2 + 5 + 1; int v2 = 7 + 13 + 1 // do something with v1, v2 } 

Il compilatore fa questo per risparmiare il sovraccarico di effettuare effettivamente una chiamata di funzione, il che implicherebbe spingere ogni parametro nello stack.

Questo può chiaramente essere fatto solo per le funzioni non virtuali. Considera cosa succederebbe se il metodo fosse sovrascritto in una sottoclass e il tipo dell’object contenente il metodo non fosse noto fino al runtime … come sarebbe il compilatore a sapere quale codice copiare: il corpo del metodo della class base o della sottoclass metodo del corpo? Poiché tutti i metodi sono virtuali per impostazione predefinita in Java, è ansible contrassegnare esplicitamente quelli che non possono essere sostituiti come final (o inserirli in una class final ). Ciò aiuterà il compilatore a capire che il metodo non sarà mai sovrascritto, ed è sicuro inserirlo in linea. (Si noti che a volte il compilatore può effettuare questa determinazione anche per i metodi non definitivi).

Inoltre, si noti la parola può nella citazione. Non è garantito che i metodi finali siano integri. Esistono vari modi per garantire che un metodo non sia in grado di essere sottolineato, ma non è ansible forzare il compilatore in linea. Quasi sempre lo saprà meglio di te quando l’inline aiuterà a ridurre la velocità del codice risultante.

Vedi wikipedia per una buona panoramica di benefici e problemi.

Chiamare una funzione non è gratuita. La macchina deve mantenere uno stack frame in modo che possa tornare alla sezione del codice chiamante quando la funzione chiamata è completa. Mantenere lo stack (inclusi i parametri di funzione di passaggio su questo stack) richiede tempo.

Quando una funzione è allineata, il compilatore sostituisce la chiamata alla funzione con il codice della funzione in modo da evitare la penalizzazione delle prestazioni di una chiamata di funzione in fase di esecuzione. Questo è uno dei classici compromessi nella programmazione: il codice run-time diventa un po ‘più grande (occupa più memoria), ma funziona un po’ più velocemente.

Supponiamo che tu abbia una class simile a questa:

 public class Demo { public void method() { // call printMessage printMessage(); } public void printMessage() { System.out.println("Hello World"); } } 

La chiamata a printMessage potrebbe essere “inline” nel modo seguente:

 public class Demo { public void method() { // call printMessage System.out.println("Hello World"); // <-- inlined } public void printMessage() { System.out.println("Hello World"); } } 

(Questo in realtà non è fatto a livello di Java (nemmeno in livello bytecode) ma durante la compilazione JIT, ma l'esempio sopra illustra il concetto di inlining.)

Consideriamo ora cosa succederebbe se il metodo printMessage fosse sovraccaricato da un'altra class , come questa:

 class SubDemo extends Demo { public void printMessage() { System.out.println("Something else"); } } 

Ora se il compilatore ha richiamato la chiamata a Demo.printMessage , sarebbe rimasto bloccato con System.out.println("Hello World"); che sarebbe sbagliato nel caso in cui l'object fosse effettivamente un'istanza di SubDemo .

Tuttavia, se il metodo è stato dichiarato final ciò non dovrebbe in nessun caso verificarsi. Se il metodo è "finale", significa che non può mai essere sostituito con una nuova definizione, quindi è sicuro inserirlo in linea!