2013-04-09 30 views
11

Diciamo che ho un ciclo che si ripete milioni di volte. All'interno di questo ciclo ho una chiamata di funzione.Parametro funzione o variabile locale

All'interno di questa funzione ho bisogno di operare su alcune variabili temporanee create proprio all'inizio. Ora, quale è meglio:

a) Creare variabile temporanea all'inizio del codice, inizializzare all'inizio del ciclo, e passarlo come parametro di funzione

b) Creare variabile temporanea solo locale al inizio della funzione chiamata?

Questa domanda è disponibile? Mi piacerebbe sapere quale punto è considerato una pratica migliore o quale è più veloce.

+1

Qualsiasi risultato risulti in codice più pulito è una pratica migliore, in questo caso, dichiarando la variabile all'interno della funzione. Se sei preoccupato per quale è più veloce, quindi punto di riferimento. – cdhowie

+1

Quindi quello che stai chiedendo è: creare la variabile nella funzione o passarla come parametro? Dovrebbe essere abbastanza comparabile. – cnicutar

+0

Ok, fantastico, grazie. – user2252786

risposta

9

Lanciamo alcune definizioni possibili per some_function(), la funzione che chiamerai dal tuo ciclo.

// Method 1 
void some_function() { 
    int temporary; 

    // Use temporary 
} 

// Method 2 
void some_function(int temporary) { 
    // Use temporary 
} 

// Method 3 
void some_function(int *temporary) { 
    // Use *temporary 
} 

Metodo 1 è probabile che sia il più leggibile di queste opzioni, e quindi è quello che io preferirei se non si dispone di un davvero buon motivo per fare qualcosa di diverso. È anche probabile che sia più veloce di uno degli altri, a meno che il compilatore non sia in grado di chiamare la funzione. Se lo è, è probabile che tutti e tre eseguano esattamente lo stesso (il metodo 3 potrebbe essere ancora più lento se il compilatore non è in grado di ottimizzare le deviazioni del puntatore).

Se il compilatore non è in linea, il metodo 2 rischia di essere più lento del metodo 1. Ciò è dovuto al fatto che, in termini di memoria allocata nello stack, sono gli stessi - gli argomenti della funzione verranno memorizzati sul impilare allo stesso modo dei locali. L'unica differenza tra un argomento di funzione e un locale in questo contesto è che all'argomento della funzione può essere assegnato un valore dal chiamante. Questo passaggio del trasferimento del valore dal chiamante alla funzione è (teoricamente) andando a rallentare l'invocazione.

Il metodo 3 è quasi certamente più lento, poiché l'accesso alla memoria temporanea includerà un livello di riferimento indiretto. Dereferenziare un puntatore non è un'operazione a basso costo rispetto all'accesso a un locale.

Naturalmente, se le prestazioni sono assolutamente critiche, è necessario valutare questi approcci. Sospetto che il metodo 1 risulterà essere il più veloce (o almeno non più lento degli altri) e inoltre mi sembra più leggibile.

+0

L'unica cosa da menzionare è stack vs heap var e possibile frammentazione se detta var è "grande". –

0

C'è una sottile differenza tra questi due approcci se si passa la variabile come puntatore, piuttosto che un valore. Il puntatore verrà inserito nello stack delle chiamate e dovrà essere referenziato per ottenere/impostare il valore.

Al contrario, impostandolo come valore locale o valore passato, il valore verrà messo in pila. Non importa se è un locale o passa per valore in quel caso ... anche se c'è un avvertimento possibile basato su come la variabile viene gestita al di fuori della funzione nel caso del passaggio per valore ... se è memorizzato in una variabile (non passando un valore letterale), deve essere prelevata dalla memoria e spinta in pila. Se è impostato da un valore letterale all'interno della funzione, è solo un letterale messo in pila e salvato un ciclo di memoria.

Una terza opzione che si omette è l'uso di una variabile globale.

Nel caso in cui il valore sia costante, sempre, quindi la risposta migliore utilizza un #define e compila direttamente nel codice come letterale.

1

Se la variabile non è necessaria al di fuori della funzione, dovrebbe trovarsi all'interno della funzione. Questo permette al compilatore di fare il miglior lavoro di ottimizzazione del codice, oltre a rendere il codice più leggibile e facile da usare (questo vale in generale, "dichiarare le variabili con il più piccolo ambito possibile", anche se per piccole funzioni, dichiarando una manciata di le variabili nella parte superiore della funzione ogni volta sono l'opzione migliore).

Dal punto di vista delle prestazioni, passare una variabile a una funzione è equivalente, o peggio che avere una variabile locale. [E ovviamente, il compilatore può allineare tutto e si finisce con lo stesso codice in entrambi i casi, ma dipende dal compilatore e dal codice che si ha].

Come altri hanno già detto, passare un puntatore a una variabile locale comporta una "penalità" per accedere al puntatore per ottenere il valore. Potrebbe non fare una grande differenza, ma quasi sicuramente fa la differenza. Questo dovrebbe essere definitivamente l'ultima risorsa. [Si noti che se la variabile è LARGE, il sovraccarico di passare una copia alla funzione potrebbe essere ancora peggiore del sovraccarico di un puntatore. Ma se assumiamo che sia un tipo semplice come int o float, un puntatore ha un overhead notevole].

Ogni volta che c'è una domanda sulle prestazioni, DEFINITIVAMENTE si dovrebbe valutare il proprio codice. Chiedere a qualcun altro su Internet può essere utile se c'è una scelta tra algoritmi per l'ordinamento o qualcosa del genere, ma se si tratta di "è meglio fare questo o quello" in alcune più sottili differenze, allora le differenze sono spesso piccolo e ciò che il tuo particolare compilatore avrà avrà molta più influenza di "che è teoricamente migliore".

Problemi correlati